예전에는 프로그램을 만들 때 기본적인 초기 값 설정과 사용 중 추가로 발생 하는 환경 정보들을 파일로 만들거나 쿠키에 넣어 관리를 했었는데 매번 파일을 읽어와 파싱 하고 적용하는 번거로운 작업들을 해야 했습니다. 

그런 작업들을 경량화된 데이터베이스인 SQLite를 이용하여 관리를 하면 좀더 편하게 작업이 될 수 있고 프로그램에서 발생 하는 여러 가지 데이터와 로그등도 쉽게 관리할 수 있습니다. 

사실 sqlite도 파일 형태의 데이터 베이스 이기 때문에 파일로 관리할 때 처럼 동시에 쓰기를 하면 오류가 발생 합니다.




1. SQLite 설치


1.1 SQLite 다운로드


제일 먼저 해야 할 일은 SQLite 홈페이지에서 필요한 파일을 다운로드 받습니다.


다운로드 페이지에 가면 운영체제 별, 종류 별로 분류가 되어 있고 하단으로 조금 스크롤을 하면

Source Code 항목에 시간이 지나면 버전 정보는 달라 지겠지만 sqlite-amalgamation-xxxxxx.zip 형태의 소스파일을 다운 받습니다. 압축 파일을 풀면 헤더 파일과 소스 파일이 있습니다.


Precompiled Binaries for Windows 항목에는 윈도우용 파일이 있는데 소스파일과 동일한 버전인 sqlite-dll-xxxx.zip 형태를 가진 파일이 존재 합니다. 여기서 32-bit, 64-bit 중 자신의 시스템에 필요한 파일을 다운로드 받습니다.


MFC Sqlite



1.2. Lib 생성


다운 받은 파일은 적당한 곳에 압축을 풀어 주세요.

sqlite3.def

sqlite3.dll

두개의 파일만 보이고 우리가 사용할 lib 파일이 보이지 않는데 lib는 생성을 해야 합니다.


개발자 명령 프롬프트를 실행 합니다.  Visual Studio가 한글인지 영문인지에 따라 한글과 영문으로 나오지만 동일한 명령어 입니다.


MFC Sqlite


저는 한글이라 이렇게 나오고 영문이면 Developer Command Prompt 이렇게 되어 있습니다. 어찌되었건 실행을 하면 콘솔 창이 하나 나옵니다.


MFC Sqlite


Developer Command Prompt 콘솔 창이 나오면

압축을 푼 디렉토리로 이동을 하고 cd D:\sqlite-dll-win64-x64-3220000

lib 생성 명령을 입력 합니다.


32 bit : D:\sqlite-dll-win64-x64-3220000>LIB /DEF:sqlite3.def

64 bit : D:\sqlite-dll-win64-x64-3220000>LIB /DEF:sqlite3.def /machine:X64

이제 sqlite3.lib 파일이 생성 되었습니다.



2. MFC 프로젝트


2.1 프로젝트 생성


프로젝트를 하나 생성해서 sqlite를 활용해 보도록 하겠습니다.

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

[단일 문서]를 설정 하는 것 이외에는 기본값으로 하고 계속 [다음]으로 넘어 갑니다.



최종단계에 도달 하면 간단한 이벤트를 사용하기 위해 [기본 클래스(A)] CFormView로 설정합니다.





2.2 설정


다운받은 source 파일 중에서 sqlite3.h 파일을 프로젝트 디렉토리로 옮기고 [기존 항목(G)]을 이용하여 추가 합니다.



생성된 Lib를 프로젝트에 추가합니다.

추가 방법은 프로젝트에 마우스를 대고 오른쪽을 눌러아신다고요. 안 손아파.



실행할떄 Dll을 찾는 경우도 있습니다. 실행위치에 복사해 줍니다.

실제 코딩을 위한 클래스를 추가해 줍니다.  파일 생성은 여기서는 DatabaseSql.cpp, DatabaseSql.h 이렇게 했습니다.



DB를 관리할 파일도 DatabaseSql.h, DatabaseSql.cpp 이렇게 두개 생성해 줍니다.

지금 생성한 4개 파일과 기존에 자동 생성된 MainFrm.h, MainFrm.cpp 두개의 파일만 코딩하면 작업이 완료 됩니다.


2.3 코딩


어떤 작업을 할건지 일단 그림을 한번 볼까요?

입력창을 4개 만들었는데 귀찮아서 앞에 있는 2개만 사용합니다.

물론 4개 다 DB에 저장을 하긴 하지만 입력하면 앞쪽 두개의 갑으로 프로젝트의 타이틀을 변경 시키는 프로그램을 만들라고 합니다.



- DatabaseSql 작업


DatabaseSql.h 에서는 쿼리 결과를 받아올 struct 생성하는 것만 보시고 나머지는 일반적인 설정들입니다. cpp 간단해서 첨부파일을 보시면 됩니다.


#include "stdafx.h"
#include "sqlite3.h"
#include 


typedef struct {
	char **pazResult;    /* Results of the query */
	int pnRow;           /* Number of result rows written here */
	int pnColumn;        /* Number of result columns written here */
	char *pzErrmsg;       /* Error msg written here */
}sqlite3_select, *sSelect;

class CDatabaseSql
{
public:
	CDatabaseSql();
	~CDatabaseSql();

	sqlite3 *pDbRef;
	char	*m_ErrMsg;

	int DatabaseOpen();  // DB 생성, 열기
	int ExecuteSqlite(CString sqlQuery);  //Insert, Update, Delete를 실행
	sqlite3_select SelectSqlite(CString sqlQuery); //select를 실행
	
	
};

- MainFrm 작업


sqlite Database 작업을 하기 MainFrm.h 파일에 다음 소스를 추가 합니다.

#include "DatabaseSql.h"

CDatabaseSql      m_DatabaseSql;

.

MainFrm.cpp 파일에 다음을 추가해서 프로그램이 실행될때 Database Table을 생성 하도록 다음 소스를 추가 합니다


int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
		//------------------------- CopyCoding Start ---------------------------------
	 
	// Create Database
	if (m_DatabaseSql.DatabaseOpen())
	{
		exit(-1);
	}
	// Create Table
	CString sql = _T("CREATE TABLE IF NOT EXISTS TB_SETTING(SEQ INTEGER PRIMARY KEY AUTOINCREMENT, SET1 TEXT, SET2 TEXT, SET3 TEXT); ");
	m_DatabaseSql.ExecuteSqlite(sql);
	
	//========================== CopyCoding ENd =================================
}

- SqliteTestView 작업


SqliteTestView.cpp에는 초기화시 DB 오픈하도록 해줍니다.


void CSqliteTestView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();

	// View에서 사용할 Database Open
	if (m_DatabaseSql.DatabaseOpen())
	{
		exit(-1);
	}
}

OnBnClickedBtnInput() 이 함수가 메인 작업입니다.

프로그램 흐름은 디비를 조회해서 자료가 있으면 읽어와서 타이틀을 변경 하고 입력한 값으로 변경합니다.  자료가 없으면 디비에 입력을 합니다.

프로그램을 하고 나니 기능을 한곳에 넣기 위해 어거지로 만든 기분이네요.


	GetDlgItemText(IDC_EDIT_VAL1, zTitle);
	GetDlgItemText(IDC_EDIT_VAL2, zVal1);
	GetDlgItemText(IDC_EDIT_VAL3, zVal2);
	GetDlgItemText(IDC_EDIT_VAL4, zVal3);
//입력란을 모두 적어줍니다.
	if (zTitle.IsEmpty() || zVal1.IsEmpty() || zVal2.IsEmpty() || zVal3.IsEmpty()) {
		MessageBox(_T("빈칸을 채워 주세요!"));
		return;
	}

	CString strSelQuery = _T("select * from TB_SETTING ;");  //쿼리 생성을 합니다.
	sqlite3_select p_selResult = m_DatabaseSql.SelectSqlite(strSelQuery); //조회 합니다.
	if (p_selResult.pnRow == 0) { //데이터가 없다고요?
		CString strInsQuery = _T("Insert into TB_SETTING VALUES( NULL,'" + zTitle + "','" + zVal1 + "','" + zVal2 + "','" + zVal3 + "');");  // 입력쿼리 생성해서
		int rc = m_DatabaseSql.ExecuteSqlite(strInsQuery);  //입력 해야죠
	}
	else {  //자료가 있네요. 아래에서 하나씩 읽어옵니다.
		for (int rowCtr = 0; rowCtr <= p_selResult.pnRow; ++rowCtr)
		{
			int colCtr = 0;
			int nCol = 1;
			int cellPosition = (rowCtr * p_selResult.pnColumn) + colCtr;

			std::string sel1 = p_selResult.pazResult[cellPosition++];
			CString zSeq(sel1.c_str());
			std::string sel2 = p_selResult.pazResult[cellPosition++];
			CString zTitle(sel2.c_str());
			std::string sel3 = p_selResult.pazResult[cellPosition++];
			CString zSet1(sel3.c_str());
			std::string sel4 = p_selResult.pazResult[cellPosition++];
			CString zSet2(sel4.c_str());
			std::string sel5 = p_selResult.pazResult[cellPosition++];
			CString zSet3(sel5.c_str());

			if (rowCtr == 0) {
				continue; //sqlite는 필드값도 가져와서 걸러줍니다.
			}

			SetValue(zTitle, zSet1);  //타이틀 변경 호출
		}

		CString strInsQuery = _T("Update TB_SETTING set TITLE='" + zTitle + "',SET1='" + zVal1 + "',SET2='" + zVal2 + "',SET3='" + zVal3 + "';"); //데이터가 존재하니 업데이트
		int rc = m_DatabaseSql.ExecuteSqlite(strInsQuery);
	}

3. 소스


Visual Studio 2017에서 생성했지만 2015에서도 작동되는걸 확인했습니다.

파일이 커서 소스들만 올리는데 실제 필요한건 앞에서도 설명드린 6개입니다.


SqliteTest.7z


res.7z


- copy coding -


+ Recent posts