본문 바로가기

오래된것

C++, ADO 그리고 MS SQL Server 2008

 C++, ADO 그리고 MS SQL Server 2008

 

  ADO 연결에 삽질했던 시기에 썼던 글입니다. 연동시 참고 할 만합니다.

 

 

 연동 제대로 하기

 

저와같이 개고생 하지 마시라고 올립니다.

 

C++, ADO 그리고 MS SQL Server 2008

 

요 3녀석 때문에 몇일동안 골치를 썩네요.

바로 '인코딩'문제때문인데요,

 

UTF-8인코딩으로 서비스를 제공해야할 필요가 있었서 적용을 하려하니, MySQL과는 다르게 인코딩방식을 지정해 주는게 없더라구요.

 

 

첫번째로 MS SQL SERVER의 인코딩 방식을 찾는라 삽질을 많이 했구요.

두번째로 ADO가 connectionstring시, CharSet=UTF8;을 하더라도, 그것이 제대로 적용이 안되어서 1차적으로 별놈의 삽질을 다했구요.

세번째로 C++에서 INSERT, SELECT, UPDATE 등의 쿼리시 데이터의 치환작업을 제대로 안해줘서 굉장하게 별난 놈의 삽질을 했네요.

 

결론은 이렇습니다.

첫번째 문제는 N계열의 CHARACTER 타입의 컬럼을 생성하면 됩니다.

NCHAR, NVARCHAR, NTEXT .. 등의 타입이 있죠. 이것은 C++의 wchar_t 와 대응됩니다.

C++의 유니코드 표현방식인 wchar_t은 UTF-8과 표현방식이 다른것은 다들 아실테구요.

 

두번째 문제는 ADO CharSet을 정하지 않는다 입니다. 정해봤자 이게 도대체 어떤식으로 작동하는지 감이 안잡히는 겁니다. 그래서 CharSet은 제거하구요.

 

세번째 문제는 받은 데이터는 UTF-8로 저장된 bytes 입니다. 1byte 들로 이루어진 데이터란 뜻이구요.

이것들을 wchar_t로 변경해야 합니다. ms-sql에 정상적인 입력을 위해서요.

변경해서 입력하면 되구요,

이제 이것들을 select 해서 받아올땐, 다시 1byte로 이루어진 UTF-8데이터로 변경해야 합니다.

역시 받아오면 변경해서 출력해 줘야 합니다.

 

이렇게 하면 MS-SQL에도 제대로된 값이 들어가서 한글표현이 잘되구요,

CLIENT측에서도 제대로된 값을 받습니다.

 

 

**위의 문제를 해결하기위한 서버측 코드입니다.

MSSQL을 접속하기 위한 ADO connectionstring = "Provider=sqloledb; Data Source=%s; uid=%s; pwd=%s; Initial Catalog=%s;"

 

 

**INSERT 시 필요한 컨버팅작업

std::string szText = recv(...); // 데이터를 받은 곳입니다. 소켓통신으로 받았죠.

swprintf_s(szQuery, 1024, L"INSERT INTO DATA_TEXT(NTXT) VALUES('%s');", UTF8TOANSI(szText).c_str());

 

 

**SELECT 시 필요한 컨버팅작업

Excute("SELECT NTXT FROM DATA_TEXT", &pPar);

std::string szText2 = ANSITOUTF8((wchar_t*)pPar->GetString("NTXT"));

 

 

std::string ANSITOUTF8(std::wstring szUnicode)

{

 std::string szRes;

 size_t   nUTF8Size = (szUnicode.size()*3)+1;

 char    *pszUTF8 = new char[nUTF8Size];

 memset(pszUTF8, 0, nUTF8Size);

 

 ::WideCharToMultiByte(CP_UTF8, 0, szUnicode.c_str(), -1, pszUTF8, nUTF8Size, NULL, NULL);

 szRes = pszUTF8;

 delete [] pszUTF8;

 return szRes;

}

std::wstring UTF8TOANSI(std::string szUTF8)

{

 std::wstring szRes;

 size_t    nUnicodeSize = szUTF8.size() + 1;

 wchar_t    *pszUnicode  = new wchar_t[nUnicodeSize];

 memset(pszUnicode, 0, nUnicodeSize);

 ::MultiByteToWideChar(CP_UTF8, 0, szUTF8.c_str(), -1, pszUnicode, nUnicodeSize);

 szRes = pszUnicode;

 delete [] pszUnicode;

 return szRes;

}

 

도움이 되시길 바랍니다.