반응형




MFC에서 SQLite3에 한글 문자열을 저장하고 다시 불러오는 간단한 예제를 만들어보았습니다.

이쪽 분야를 전문적으로 작성하지 않기 때문에 좀 이상하게 작성된게 있을 수도 있습니다^^;






MFC에서 사용할 SQLIte를 다운로드 받아야 합니다. 


https://www.sqlite.org/download.html 에서  SQLite 소스 코드와 DLL 파일을 다운로드 합니다.

생성한 프로젝트에 따라 x86 또는 x64 DLL을 사용합니다. 본 포스트에서는 x64를 사용합니다. 





압축을 풀어서 C:\SQLite3에 복사해줍니다. 





개발자 명령 프롬프트 또는 Developer Command Prompt를 검색하여 실행합니다.

Visual Studio 2019에서도 동일하게 진행할 수 있습니다.





다음 명령을 사용하여 lib 파일을 생성합니다.

32비트인 경우에는 x64대신 x86을 사용하면 됩니다.


lib /def:sqlite3.def /machine:x64





새로운 MFC 프로젝트를  생성합니다. 





응용 프로그램 종류로 대화 상자 기반을 선택하고, SDL은 체크해제 한 후, 마침 버튼을 클릭합니다.





솔루션 플랫폼을 x64로 변경합니다.



메뉴에서 프로젝트 > 속성을 선택하고  구성을 모든 구성으로 변경합니다.




왼쪽 메뉴에서 C/C++를 선택한 후, 추가 포함 디렉토리 항목에 C:\SQlite3을 입력합니다. 





왼쪽 메뉴에서 링커를 선택하고 추가 라이브러리 디렉터리 항목에 C:\SQLite3을 입력합니다.





왼쪽 메뉴에서 디버깅을 선택한 후, 환경 항목에 다음을 입력합니다. 


PATH=C:\SQLite3;%PATH%





프로젝트 창에서 리소스 뷰를 선택합니다. 





 Dialog 항목에 있는 IDD_ABOUTBOX 아래에 있는 다이얼로그를 선택합니다. 

리소스 뷰가 보이지 않는 경우 메뉴에서 보기 > 리소스 뷰를 선택하세요. 





다음처럼 UI를 구성하고 변수를 추가해줍니다. 





리스트 컨트롤의 속성에서 Single Selection을 True로 변경합니다.



View를 Report로 변경합니다.



파일 이름에 Dlg가 포함된 cpp 파일에 코드를 추가할 차례입니다. 

제 경우에는 SQLite3_ExampleDlg.cpp 입니다. 



필요한 헤더파일과 함수 그리고 SQLite 라이브러리를 로드하기 위한  코드를 추가합니다.


#include "sqlite3.h"
#include <assert.h>

#pragma comment(lib, "sqlite3.lib")



// SQLite는 UTF8을 사용하기 때문에 코드 변환이 필요합니다.
// 출처 - http://dolphin.ivyro.net/file/algorithm/SQLite/tutoria03.html
int AnsiToUTF8(char* szSrc, char* strDest, int destSize)
{
WCHAR szUnicode[255];
char szUTF8code[255];

int nUnicodeSize = MultiByteToWideChar(CP_ACP, 0, szSrc, (int)strlen(szSrc), szUnicode, sizeof(szUnicode));
int nUTF8codeSize = WideCharToMultiByte(CP_UTF8, 0, szUnicode, nUnicodeSize, szUTF8code, sizeof(szUTF8code), NULL, NULL);
assert(destSize > nUTF8codeSize);
memcpy(strDest, szUTF8code, nUTF8codeSize);
strDest[nUTF8codeSize] = 0;
return nUTF8codeSize;
}

int UTF8ToAnsi(char* szSrc, char* strDest, int destSize)
{
WCHAR szUnicode[255];
char szAnsi[255];

int nSize = MultiByteToWideChar(CP_UTF8, 0, szSrc, -1, 0, 0);
int nUnicodeSize = MultiByteToWideChar(CP_UTF8, 0, szSrc, -1, szUnicode, nSize);
int nAnsiSize = WideCharToMultiByte(CP_ACP, 0, szUnicode, nUnicodeSize, szAnsi, sizeof(szAnsi), NULL, NULL);
assert(destSize > nAnsiSize);
memcpy(strDest, szAnsi, nAnsiSize);
strDest[nAnsiSize] = 0;
return nAnsiSize;
}





초기에 필요한 데이터베이스 파일 생성, 테이블 생성을 합니다. 

그리고  데이터베이스로부터 데이터를 가져와 리스트 컨트롤에 보여줍니다.

BOOL CSQLite3ExampleDlg::OnInitDialog()
{
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

// TODO: 여기에 추가 초기화 작업을 추가합니다.

// 한줄 선택
m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

// 리스트 컨트롤에 컬럼 이름 입력
m_list.InsertColumn(0, L"이름");
m_list.SetColumnWidth(0, 120);
m_list.InsertColumn(1, L"전화번호");
m_list.SetColumnWidth(1, 240);



// 데이터베이스 파일 생성 및 열기
sqlite3 *db;
sqlite3_stmt *stmt;
char *errmsg = NULL;

int rc = sqlite3_open("test.db", &db);

if (rc != SQLITE_OK)
{
printf("Failed to open DB\n");
sqlite3_close(db);
exit(1);
}


//SQL 테이블 생성
char *sql;
sql = "CREATE TABLE IF NOT EXISTS DB("
"ID INTEGER PRIMARY        KEY AUTOINCREMENT,"
"NAME          TEXT NOT NULL,"
"TEL           TEXT NOT NULL);";

rc = sqlite3_exec(db, sql, NULL, NULL, &errmsg);

if (rc != SQLITE_OK)
{
printf("create table");
sqlite3_free(errmsg);
sqlite3_close(db);
exit(1);
}



      // 테이블을 읽어와 리스트 컨트롤에 보여주기
sqlite3_prepare_v2(db, "select * from db", -1, &stmt, NULL);

while (sqlite3_step(stmt) != SQLITE_DONE) {
int i;
int num_cols = sqlite3_column_count(stmt);


char szAnsi[300];
UTF8ToAnsi((char *)sqlite3_column_text(stmt, 1), szAnsi, 300);
CString name(szAnsi);

UTF8ToAnsi((char *)sqlite3_column_text(stmt, 2), szAnsi, 300);
CString tel(szAnsi);

int nItem = m_list.InsertItem(0, name);
m_list.SetItemText(nItem, 1, tel);

}

sqlite3_finalize(stmt);

sqlite3_close(db);


return TRUE;  // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.
}




추가 버튼 클릭시 실행되는 코드입니다. 


void CSQLite3ExampleDlg::OnBnClickedAdd()
{

// 에디터 박스에 입력된 데이터를 리스트컨트롤에 입력합니다.
CString name;
m_name.GetWindowText(name);

CString tel;
m_tel.GetWindowText(tel);


int nItem = m_list.InsertItem(0, name);
m_list.SetItemText(nItem, 1, tel);


m_name.SetWindowTextW(L"");
m_tel.SetWindowTextW(L"");



sqlite3 *db;
int rc = sqlite3_open("test.db", &db);

if (rc != SQLITE_OK)
{
printf("Failed to open DB\n");
sqlite3_close(db);
exit(1);
}



char * s_name;

int sLen = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
s_name = new char[sLen + 1];
WideCharToMultiByte(CP_ACP, 0, name, -1, s_name, sLen, NULL, NULL);

char szName[100];
AnsiToUTF8(s_name, szName, 100);

delete[]s_name;




char * s_tel;

sLen = WideCharToMultiByte(CP_ACP, 0, tel, -1, NULL, 0, NULL, NULL);
s_tel = new char[sLen + 1];
WideCharToMultiByte(CP_ACP, 0, tel, -1, s_tel, sLen, NULL, NULL);

char szTel[100];
AnsiToUTF8(s_tel, szTel, 100);

delete[]s_tel;

 

char *errmsg = NULL;
char sql[255] = { 0 };
sprintf(sql, "insert into db(name, tel) values('%s','%s');", szName, szTel);

if (SQLITE_OK != sqlite3_exec(db, sql, NULL, NULL, &errmsg))
{
printf("insert");
}

sqlite3_close(db);


}




삭제 버튼 클릭시 실행되는 코드입니다.


void CSQLite3ExampleDlg::OnBnClickedRemove()
{
// 리스트 컨트롤에서 선택한 아이템을 제거합니다.
int row = m_list.GetSelectionMark();
CString name = m_list.GetItemText(row, 0);


char * s_name;

int sLen = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
s_name = new char[sLen + 1];
WideCharToMultiByte(CP_ACP, 0, name, -1, s_name, sLen, NULL, NULL);

char szName[100];
AnsiToUTF8(s_name, szName, 100);

delete[]s_name;



sqlite3 *db;
int rc = sqlite3_open("test.db", &db);

if (rc != SQLITE_OK)
{
printf("Failed to open DB\n");
sqlite3_close(db);
exit(1);
}


char *errmsg = NULL;
char sql[255] = { 0 };
sprintf(sql, "delete from db where name = '%s';", szName);

if (SQLITE_OK != sqlite3_exec(db, sql, NULL, NULL, &errmsg))
{
printf("delete");
}



sqlite3_close(db);


m_list.DeleteItem(row);


}



작성 2020. 3. 23


반응형

포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

여러분의 응원으로 좋은 컨텐츠가 만들어집니다.
지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요.

+ Recent posts