http://www.cnblogs.com/giszhang/articles/1307509.html
VC2005 +SQLite 3.6.3 編譯、測試開發手記
偶然的機會對SQLite有了興趣,花了半天的時間小小研究了一下,包括VC2005環境下SQLite的編譯,開發測試等。
初次接觸,只是測試了基本的數據庫操作功能,更多的高級功能有待以後繼續深入研究,廢話少說,言歸正傳。
現在SQLite的最新版本是 V3.6.3,發佈於2008年9月22,詳見http://sqlite.org/的介紹。
還是補充一句什麼是SQLite吧,“SQLite是一款輕型的數據庫,它的設計目標是嵌入式的,而且目前已經在很多嵌入式產品中使用了它,它佔用資源非常的低,在嵌入式設備中,可能只需要幾百K的內存就夠了。它能夠支持Windows/Linux/Unix等等主流的操作系統,同時能夠跟很多程序語言相結合,比如Tcl、PHP、Java等,還有ODBC接口,同樣比起Mysql、PostgreSQL這兩款開源世界著名的數據庫管理系統來講,它的處理速度比他們都快。”
簡單的說,SQLite的特點就是小巧、高效,SQLite數據庫只有一個文件,也可以說是文件數據庫吧,對於某些桌面應用以及嵌入式應用來說,SQLite可以提供相當高效的數據存儲方案。如果你正在位自己的應用程序尋找一種數據管理方案的話,不妨考慮一下SQLite。
接着說SQLite如何在VC環境下進行開發。
從SQLite官網上當下來的,可以有SQLite命令行程序,還可以有運行支持的DLL,當然開源的SQLite還提供了完整的源碼。
嵌入SQLite開發的程序發佈時,需要提供SQLiteDll就行了,但是對於開發者來說,最方便的還是用Lib輔助開發,因此我們自己來編譯SQLite就很有必要了(當然,也可以通過DLL直接獲取Lib,但自己編譯出來的感覺不一樣,哈哈:) )。
好了,首先從http://sqlite.org/download.html上把最新的源碼下載下來,注意,Source Code有好幾個版本,沒搞太清楚各個版本都是幹啥的,這裏我們下載下來sqlite-source-3_6_3.zip(Zip格式的,不是gz的,呵呵),當然把sqlite-amalgamation-3.6.3.tar.gz下載下來也是最好的,因爲我們後面可能需要其中的一個文件(sqlite3.def),不想下的話,從別的地方找一下就Ok了。
有了源碼以後,我們先建立一個Win32的空白DLL項目,比如這裏項目爲SQLiteLib,然後把剛纔下載的SQLite源碼解壓到一個文件夾(如sqlite-source),把這個文件夾複製到項目文件夾裏,並加入到新建的工程中。
這樣就完成了第一步,但是這個時侯如果你編譯的話,會發現有好幾個錯誤和N個警告。首先在項目解決方案裏移除以下幾個文件tclsqlite.c,shell.c,rtree.c,fts3.c,fts3_hash.c,fts3_icu.c,fts3_porter.c,fts3_tokenizer1.c,fts3_tokenizer.c。
其中tclsqlite.c用於生成基於TCL的API,如果要編譯,這需要另外下載tcl.h;shell.c用於生成命令行模式的sqlite.exe;rTree.c是建立數據庫R樹索引的模塊,fts3*.c是全文索引模塊,這兩個擴展模塊直接編譯的時候會提示以下錯誤,
1>fts3.obj : errorLNK2005: _sqlite3_extension_init 已經在 rtree.obj 中定義
1>fts3.obj : errorLNK2005: _sqlite3_api 已經在 rtree.obj 中定義
1>fts3_tokenizer.obj :error LNK2005: _sqlite3_api 已經在 rtree.obj 中定義
至於原因,一時半會兒也沒找出來,就先不管它了,從項目中移除上面幾個文件再編譯就Ok了(移除Rtree.c是因爲發現用其編譯出來的庫時會出錯)。
(呵呵,初次測試的目的是基本應用,所以具體錯誤的原因就沒深究,有興趣的可以共同探討一下,主要是Rtree和全文檢索模塊的應用)
接下里,我們在工程屬性裏,把“N”個警告忽略掉,配置屬性àC/C++->高級à禁用特定警告裏,設置“4267;4244;4018;4996;”。
然後再編譯世界就清淨了,呵呵,順利編譯出的有DLL和Lib文件,接下里我們對SQLite進行簡單的功能測試,體驗一下SQLite編程的便利。
/************************************************/
建立一個新的測試工程,這裏我們選擇MFC應用程序(DialogBased),例如項目SQLiteDEmo。
在項目文件夾下建立一個Lib文件夾,把剛纔生成的Lib文件和Sqlite3.h複製到該文件夾下,爲了方便可以把SQLiteLib和SQLiteDemo在一個解決方案裏管理,設置共同的輸出路徑,並在生成時間裏自動拷貝庫文件,這樣不用每次都手動來操作,還能保證用到的都是最新的編譯版本。
在SQLiteDemo項目屬性裏,配置屬性à鏈接器à輸入à附加依賴性,設置爲“$(SolutionDir)lib/SQLite3.lib”,這樣就把SQLite庫引用到了我們的工程中。
然後,在用到SQLite的文件裏包含頭文件 #include "../lib/sqlite3.h"。
/************************************************/
接下來,我們進行簡單的SQLite應用。
//連接數據庫
void CSQLiteDemoDlg::OnBnClickedButtonConnect()
{
UpdateData();
m_strDB.Trim(_T(" /t/n"));;
if( m_strDB.IsEmpty() )
{
//AfxMessageBox(_T("請檢查數據庫參數!"));
m_strResult += _T("請檢查數據庫參數!/r/n");
return;
}
//
int result = 0;
//
LPSTR szTmp = new char[MAX_PATH];
wsprintfA(szTmp, "%ls", m_strDB);
result = sqlite3_open( szTmp, &m_db );//關鍵代碼, 連接數據庫
if( result )
{
//AfxMessageBox(_T("連接數據庫失敗!"));
m_strResult += m_strDB;
m_strResult += _T("/r/n");
m_strResult += _T("連接數據庫失敗!/r/n");
sqlite3_close(m_db);
}
else
{
m_strResult += m_strDB;
m_strResult += _T("/r/n");
SqliteQuery(_T("select name, sql from sqlite_master"));
//AfxMessageBox(_T("連接數據庫成功!"));
m_strResult += _T("連接數據庫成功!/r/n");
}
//
delete[] szTmp;
}
//執行語句
void CSQLiteDemoDlg::SqliteExec(CString strSQL)
{
strSQL.Trim(_T(" /t/n"));
if( strSQL.IsEmpty() )
{
//AfxMessageBox(_T("請檢查參數!"));
m_strResult += _T("請檢查執行語句!/r/n");
UpdateData(FALSE);
return;
}
//
int result = 0;
//
LPSTR szTmp = new char[MAX_PATH];
wsprintfA(szTmp, "%ls", strSQL);
LPSTR szMsg = NULL;
result = sqlite3_exec( m_db, szTmp, 0, 0, &szMsg);
if( result!=SQLITE_OK )
{
//AfxMessageBox(CString(szMsg));
m_strResult += CString(szMsg);
m_strResult += _T("/r/n");
}
delete[] szTmp;
}
//查詢
void CSQLiteDemoDlg::SqliteQuery(CString strQuery)
{
m_strResult += _T("-----------------------------------/r/n");
double dbStartTime = clock();
//
char **ppTb = NULL;
int nRow, nCol;
nRow = nCol = 0;
//
strQuery.Trim(_T(" /t/n"));;
if( strQuery.IsEmpty() )
{
//AfxMessageBox(_T("請檢查查詢參數!"));
m_strResult += _T("請檢查查詢參數!/r/n");
return;
}
m_strResult += strQuery;
m_strResult += _T("/r/n");
int result = 0;
//
LPSTR szTmp = new char[MAX_PATH];
wsprintfA(szTmp, "%ls", strQuery);
LPSTR szMsg = NULL;
result = sqlite3_get_table( m_db, szTmp, &ppTb, &nRow, &nCol, &szMsg );
if( result!=SQLITE_OK )
AfxMessageBox(CString(szMsg));
else
{
CString strRes;
for( int i=0;i<=nRow;i++ )
{
strRes = _T("");
for( int j=0;j<nCol;j++ )
{
if( j>0 )
strRes += _T("/t| ");
strRes += *(ppTb + i*nCol + j);
}
strRes += "/r/n";
m_strResult += strRes;
}
}
m_strResult += _T("-----------------------------------/r/n");
double dbEndTime = clock();
CString strTime;
strTime.Format(_T("查詢花費時間: %.2f毫秒"), (double)(dbEndTime-dbStartTime));
m_strResult += strTime;
m_strResult += _T("/r/n");
//
sqlite3_free_table(ppTb);
delete[] szTmp;
UpdateData(FALSE);
}
///////////////////////////////////////////////////////////////////////////
以上是簡單的功能測試,測試工程點擊這裏SQLiteDemo.zip這裏 下載。
歡迎大家就SQLite進行交流,好東西大家分享~~