SQLite的C++類,同時支援ANSI 和UNICODE編碼
阿新 • • 發佈:2019-01-23
源地址:http://blog.csdn.net/chinamming/article/details/17049575
標頭檔案(SQLite.h)
/******************************************************************** filename: SQLite.h created: 2012-11-05 author: firehood purpose: SQLite資料庫操作類 *********************************************************************/ #pragma once #include <windows.h> #include "..\SQLite\sqlite3.h" #pragma comment(lib,"SQLite.lib") typedef BOOL (WINAPI *QueryCallback) (void *para, int n_column, char **column_value, char **column_name); typedef enum _SQLITE_DATATYPE { SQLITE_DATATYPE_INTEGER = SQLITE_INTEGER, SQLITE_DATATYPE_FLOAT = SQLITE_FLOAT, SQLITE_DATATYPE_TEXT = SQLITE_TEXT, SQLITE_DATATYPE_BLOB = SQLITE_BLOB, SQLITE_DATATYPE_NULL= SQLITE_NULL, }SQLITE_DATATYPE; class SQLite; class SQLiteDataReader { public: SQLiteDataReader(sqlite3_stmt *pStmt); ~SQLiteDataReader(); public: // 讀取一行資料 BOOL Read(); // 關閉Reader,讀取結束後呼叫 void Close(); // 總的列數 int ColumnCount(void); // 獲取某列的名稱 LPCTSTR GetName(int nCol); // 獲取某列的資料型別 SQLITE_DATATYPE GetDataType(int nCol); // 獲取某列的值(字串) LPCTSTR GetStringValue(int nCol); // 獲取某列的值(整形) int GetIntValue(int nCol); // 獲取某列的值(長整形) long GetInt64Value(int nCol); // 獲取某列的值(浮點形) double GetFloatValue(int nCol); // 獲取某列的值(二進位制資料) const BYTE* GetBlobValue(int nCol, int &nLen); private: sqlite3_stmt *m_pStmt; }; class SQLiteCommand { public: SQLiteCommand(SQLite* pSqlite); SQLiteCommand(SQLite* pSqlite,LPCTSTR lpSql); ~SQLiteCommand(); public: // 設定命令 BOOL SetCommandText(LPCTSTR lpSql); // 繫結引數(index為要繫結引數的序號,從1開始) BOOL BindParam(int index, LPCTSTR szValue); BOOL BindParam(int index, const int nValue); BOOL BindParam(int index, const double dValue); BOOL BindParam(int index, const unsigned char* blobValue, int nLen); // 執行命令 BOOL Excute(); // 清除命令(命令不再使用時需呼叫該介面清除) void Clear(); private: SQLite *m_pSqlite; sqlite3_stmt *m_pStmt; }; class SQLite { public: SQLite(void); ~SQLite(void); public: // 開啟資料庫 BOOL Open(LPCTSTR lpDbFlie); // 關閉資料庫 void Close(); // 執行非查詢操作(更新或刪除) BOOL ExcuteNonQuery(LPCTSTR lpSql); BOOL ExcuteNonQuery(SQLiteCommand* pCmd); // 查詢 SQLiteDataReader ExcuteQuery(LPCTSTR lpSql); // 查詢(回撥方式) BOOL ExcuteQuery(LPCTSTR lpSql,QueryCallback pCallBack); // 開始事務 BOOL BeginTransaction(); // 提交事務 BOOL CommitTransaction(); // 回滾事務 BOOL RollbackTransaction(); // 獲取上一條錯誤資訊 LPCTSTR GetLastErrorMsg(); public: friend class SQLiteCommand; private: sqlite3 *m_db; };
原始檔(SQLite.cpp)
/******************************************************************** filename: SQLite.cpp created: 2012-11-05 author: firehood purpose: SQLite資料庫操作類 *********************************************************************/ #include "SQLite.h" const char* WcharToUtf8(const wchar_t *pwStr) { if (pwStr == NULL) { return NULL; } int len = WideCharToMultiByte(CP_UTF8, 0, pwStr, -1, NULL, 0, NULL, NULL); if (len <= 0) { return NULL; } char *pStr = new char[len]; WideCharToMultiByte(CP_UTF8, 0, pwStr, -1, pStr, len, NULL, NULL); return pStr; } const wchar_t* Utf8ToWchar(const char *pStr) { if (pStr == NULL) { return NULL; } int len = MultiByteToWideChar(CP_UTF8, 0, pStr, -1, NULL, 0); if (len <= 0) { return NULL; } wchar_t *pwStr = new wchar_t[len]; MultiByteToWideChar(CP_UTF8, 0, pStr, -1, pwStr, len); return pwStr; } SQLite::SQLite(void): m_db(NULL) { } SQLite::~SQLite(void) { Close(); } BOOL SQLite::Open(LPCTSTR lpDbFlie) { if(lpDbFlie == NULL) { return FALSE; } #ifdef UNICODE if(sqlite3_open16(lpDbFlie,&m_db) != SQLITE_OK) #else if(sqlite3_open(lpDbFlie,&m_db) != SQLITE_OK) #endif { return FALSE; } return TRUE; } void SQLite::Close() { if(m_db) { sqlite3_close(m_db); m_db = NULL; } } BOOL SQLite::ExcuteNonQuery(LPCTSTR lpSql) { if(lpSql == NULL) { return FALSE; } sqlite3_stmt* stmt; #ifdef UNICODE if(sqlite3_prepare16_v2(m_db, lpSql, -1, &stmt, NULL) != SQLITE_OK) #else if(sqlite3_prepare_v2(m_db, lpSql, -1, &stmt, NULL) != SQLITE_OK) #endif { return FALSE; } sqlite3_step(stmt); return (sqlite3_finalize(stmt) == SQLITE_OK) ? TRUE : FALSE ; } BOOL SQLite::ExcuteNonQuery(SQLiteCommand* pCmd) { if(pCmd == NULL) { return FALSE; } return pCmd->Excute(); } // 查詢(回撥方式) BOOL SQLite::ExcuteQuery(LPCTSTR lpSql,QueryCallback pCallBack) { if(lpSql == NULL || pCallBack == NULL) { return FALSE; } char *errmsg = NULL; #ifdef UNICODE const char *szSql = WcharToUtf8(lpSql); if(sqlite3_exec(m_db, szSql, pCallBack, NULL, &errmsg) != SQLITE_OK) { delete[] szSql; return FALSE; } delete[] szSql; #else if(sqlite3_exec(m_db, lpSql, pCallBack, NULL, &errmsg) != SQLITE_OK) { return FALSE; } #endif return TRUE; } // 查詢 SQLiteDataReader SQLite::ExcuteQuery(LPCTSTR lpSql) { if(lpSql == NULL) { return FALSE; } sqlite3_stmt* stmt; #ifdef UNICODE if(sqlite3_prepare16_v2(m_db, lpSql, -1, &stmt, NULL) != SQLITE_OK) #else if(sqlite3_prepare_v2(m_db, lpSql, -1, &stmt, NULL) != SQLITE_OK) #endif { return FALSE; } return SQLiteDataReader(stmt); } // 開始事務 BOOL SQLite::BeginTransaction() { char * errmsg = NULL; if(sqlite3_exec(m_db,"BEGIN TRANSACTION;",NULL,NULL,&errmsg) != SQLITE_OK) { return FALSE; } return TRUE; } // 提交事務 BOOL SQLite::CommitTransaction() { char * errmsg = NULL; if(sqlite3_exec(m_db,"COMMIT TRANSACTION;;",NULL,NULL,&errmsg) != SQLITE_OK) { return FALSE; } return TRUE; } // 回滾事務 BOOL SQLite::RollbackTransaction() { char * errmsg = NULL; if(sqlite3_exec(m_db,"ROLLBACK TRANSACTION;",NULL,NULL,&errmsg) != SQLITE_OK) { return FALSE; } return TRUE; } // 獲取上一條錯誤資訊 LPCTSTR SQLite::GetLastErrorMsg() { #ifdef UNICODE return (LPCTSTR)sqlite3_errmsg16(m_db); #else return sqlite3_errmsg(m_db); #endif } SQLiteDataReader::SQLiteDataReader(sqlite3_stmt *pStmt): m_pStmt(pStmt) { } SQLiteDataReader::~SQLiteDataReader() { Close(); } // 讀取一行資料 BOOL SQLiteDataReader::Read() { if(m_pStmt == NULL) { return FALSE; } if(sqlite3_step(m_pStmt) != SQLITE_ROW) { return FALSE; } return TRUE; } // 關閉Reader,讀取結束後呼叫 void SQLiteDataReader::Close() { if(m_pStmt) { sqlite3_finalize(m_pStmt); m_pStmt = NULL; } } // 總的列數 int SQLiteDataReader::ColumnCount(void) { return sqlite3_column_count(m_pStmt); } // 獲取某列的名稱 LPCTSTR SQLiteDataReader::GetName(int nCol) { #ifdef UNICODE return (LPCTSTR)sqlite3_column_name16(m_pStmt, nCol); #else return (LPCTSTR)sqlite3_column_name(m_pStmt, nCol); #endif } // 獲取某列的資料型別 SQLITE_DATATYPE SQLiteDataReader::GetDataType(int nCol) { return (SQLITE_DATATYPE)sqlite3_column_type(m_pStmt, nCol); } // 獲取某列的值(字串) LPCTSTR SQLiteDataReader::GetStringValue(int nCol) { #ifdef UNICODE return (LPCTSTR)sqlite3_column_text16(m_pStmt, nCol); #else return (LPCTSTR)sqlite3_column_text(m_pStmt, nCol); #endif } // 獲取某列的值(整形) int SQLiteDataReader::GetIntValue(int nCol) { return sqlite3_column_int(m_pStmt, nCol); } // 獲取某列的值(長整形) long SQLiteDataReader::GetInt64Value(int nCol) { return (long)sqlite3_column_int64(m_pStmt, nCol); } // 獲取某列的值(浮點形) double SQLiteDataReader::GetFloatValue(int nCol) { return sqlite3_column_double(m_pStmt, nCol); } // 獲取某列的值(二進位制資料) const BYTE* SQLiteDataReader::GetBlobValue(int nCol, int &nLen) { nLen = sqlite3_column_bytes(m_pStmt, nCol); return (const BYTE*)sqlite3_column_blob(m_pStmt, nCol); } SQLiteCommand::SQLiteCommand(SQLite* pSqlite): m_pSqlite(pSqlite), m_pStmt(NULL) { } SQLiteCommand::SQLiteCommand(SQLite* pSqlite,LPCTSTR lpSql): m_pSqlite(pSqlite), m_pStmt(NULL) { SetCommandText(lpSql); } SQLiteCommand::~SQLiteCommand() { } BOOL SQLiteCommand::SetCommandText(LPCTSTR lpSql) { #ifdef UNICODE if(sqlite3_prepare16_v2(m_pSqlite->m_db, lpSql, -1, &m_pStmt, NULL) != SQLITE_OK) #else if(sqlite3_prepare_v2(m_pSqlite->m_db, lpSql, -1, &m_pStmt, NULL) != SQLITE_OK) #endif { return FALSE; } return TRUE; } BOOL SQLiteCommand::BindParam(int index, LPCTSTR szValue) { #ifdef UNICODE if(sqlite3_bind_text16(m_pStmt, index, szValue, -1, SQLITE_TRANSIENT) != SQLITE_OK) #else if(sqlite3_bind_text(m_pStmt, index, szValue,-1, SQLITE_TRANSIENT) != SQLITE_OK) #endif { return FALSE; } return TRUE; } BOOL SQLiteCommand::BindParam(int index, const int nValue) { if(sqlite3_bind_int(m_pStmt, index, nValue) != SQLITE_OK) { return FALSE; } return TRUE; } BOOL SQLiteCommand::BindParam(int index, const double dValue) { if(sqlite3_bind_double(m_pStmt, index, dValue) != SQLITE_OK) { return FALSE; } return TRUE; } BOOL SQLiteCommand::BindParam(int index, const unsigned char* blobBuf, int nLen) { if(sqlite3_bind_blob(m_pStmt, index, blobBuf,nLen,NULL) != SQLITE_OK) { return FALSE; } return TRUE; } BOOL SQLiteCommand::Excute() { sqlite3_step(m_pStmt); return (sqlite3_reset(m_pStmt) == SQLITE_OK) ? TRUE : FALSE ; } void SQLiteCommand::Clear() { if(m_pStmt) { sqlite3_finalize(m_pStmt); } }
使用方法
通過SQLite類操作資料庫的基本程式碼如下:void SqliteOperate() { TCHAR *szDbPath = _T("Book.db"); ::DeleteFile(szDbPath); SQLite sqlite; // 開啟或建立資料庫 //****************************************************** if(!sqlite.Open(szDbPath)) { _tprintf(_T("%s\n"),sqlite.GetLastErrorMsg()); return; } //****************************************************** // 建立資料庫表 //****************************************************** TCHAR sql[512] = {0}; _stprintf(sql,_T("%s"), _T("CREATE TABLE [Book] (") _T("[id] INTEGER NOT NULL PRIMARY KEY, ") _T("[name] NVARCHAR(20), ") _T("[author] NVARCHAR(20), ") _T("[catagory_id] INTEGER REFERENCES [Category]([id]), ") _T("[abstruct] NVARCHAR(100) ,") _T("[path] NVARCHAR(50), ") _T("[image] BLOB);") _T("CREATE INDEX [Book_id] ON [Book] ([id]);") ); if(!sqlite.ExcuteNonQuery(sql)) { printf("Create database table failed...\n"); } //****************************************************** // 插入資料【普通方式】 DWORD dwBeginTick = GetTickCount(); //****************************************************** // 當一次性插入多條記錄時候,採用事務的方式,提高效率 sqlite.BeginTransaction(); // 批量插入資料 for(int i=0;i<1000;i++) { memset(sql,0,sizeof(sql)); _stprintf(sql,_T("insert into Book(name,author,catagory_id) values('紅高粱%d','莫言',1)"),i); if(!sqlite.ExcuteNonQuery(sql)) { _tprintf(_T("%s\n"),sqlite.GetLastErrorMsg()); break; } } // 提交事務 sqlite.CommitTransaction(); printf("Insert Data Take %dMS...\n",GetTickCount()-dwBeginTick); //****************************************************** // 插入資料【通過引數繫結的方式,提交批量資料時,比上面的普通模式效率更高(提高約45%),同時可支援插入二進位制資料】 dwBeginTick = GetTickCount(); //****************************************************** // 當一次性插入多條記錄時候,採用事務的方式,提高效率 sqlite.BeginTransaction(); memset(sql,0,sizeof(sql)); _stprintf(sql,_T("insert into Book(name,author,catagory_id,image) values(?,'韓寒',?,?)")); SQLiteCommand cmd(&sqlite,sql); // 批量插入資料 for(int i=0;i<1000;i++) { TCHAR strValue[16] = {0}; _stprintf(strValue,_T("他的國%d"),i); // 繫結第一個引數(name欄位值) cmd.BindParam(1,strValue); // 繫結第二個引數(catagory_id欄位值) cmd.BindParam(2,20); BYTE imageBuf[] = {0xff,0xff,0xff,0xff}; // 繫結第三個引數(image欄位值,二進位制資料) cmd.BindParam(3,imageBuf,sizeof(imageBuf)); if(!sqlite.ExcuteNonQuery(&cmd)) { _tprintf(_T("%s\n"),sqlite.GetLastErrorMsg()); break; } } // 清空cmd cmd.Clear(); // 提交事務 sqlite.CommitTransaction(); printf("Insert Data Take %dMS...\n",GetTickCount()-dwBeginTick); //****************************************************** // 查詢 dwBeginTick = GetTickCount(); //****************************************************** memset(sql,0,sizeof(sql)); _stprintf(sql,_T("%s"),_T("select * from Book where name = '他的國345'")); SQLiteDataReader Reader = sqlite.ExcuteQuery(sql); int index = 0; int len = 0; while(Reader.Read()) { _tprintf( _T("***************【第%d條記錄】***************\n"),++index); _tprintf( _T("欄位名:%s 欄位值:%d\n"),Reader.GetName(0),Reader.GetIntValue(0)); _tprintf( _T("欄位名:%s 欄位值:%s\n"),Reader.GetName(1),Reader.GetStringValue(1)); _tprintf( _T("欄位名:%s 欄位值:%s\n"),Reader.GetName(2),Reader.GetStringValue(2)); _tprintf( _T("欄位名:%s 欄位值:%d\n"),Reader.GetName(3),Reader.GetIntValue(3)); _tprintf( _T("欄位名:%s 欄位值:%s\n"),Reader.GetName(4),Reader.GetStringValue(4)); // 讀取圖片二進位制檔案 const BYTE *ImageBuf = Reader.GetBlobValue(6,len); _tprintf( _T("*******************************************\n")); } Reader.Close(); printf("Query Take %dMS...\n",GetTickCount()-dwBeginTick); //****************************************************** // 關閉資料庫 sqlite.Close(); }
執行結果
Insert Data Take 645MS...
Insert Data Take 229MS...
***************【第1條記錄】***************
欄位名:id 欄位值:1346
欄位名:name 欄位值:他的國345
欄位名:author 欄位值:韓寒
欄位名:catagory_id 欄位值:20
欄位名:abstruct 欄位值:(null)
*******************************************
執行結果
Insert Data Take 645MS...
Insert Data Take 229MS...
***************【第1條記錄】***************
欄位名:id 欄位值:1346
欄位名:name 欄位值:他的國345
欄位名:author 欄位值:韓寒
欄位名:catagory_id 欄位值:20
欄位名:abstruct 欄位值:(null)
*******************************************