SQLite3数据库Native C++封装类(Unicode)CppSQLite3U的初步认识与使用

来源:互联网 发布:扬州网络电视台回看 编辑:程序博客网 时间:2024/05/29 10:20

SQLite3数据库Native C++封装类(Unicode)CppSQLite3U的初步认识与使用  

(1)

  http://www.sqlite.org/cvstrac/wiki?p=SqliteWrappers

  从上面的网址可以找到对SQLite数据库的C API的各种语言的封装。包括c、c++、vb、c#.net、delphi、Lisp、D、Java、Javascript、Objective-C、Perl、PHP、Python、Ruby、Lua、Fortran等等。从这也可以看出SQLite数据库作为本地数据存储工具而得到的广泛应用。单单是“C++ Wrappers”也有几十种,常见的如:easySQLite、SQLite++、CppSQLite、CppSQLiteU等等。因为我通常是在Windows CE嵌入式操作系统上开发APP,而Windows CE操作系统只支持Unicode字符集,所以今天要学习和测试的是Unicode版“C++ Wrappers”:CppSQLiteU

(2)

  因为是在Windows CE操作系统上使用SQLite,所以在使用CppSQLiteU之前,要先编译针对Windows CE平台的SQLite3 DLL。这一步省了,我直接借用了别人已经编译好的。

(3)

  下面是一个简单测试示例,主要是利用class CppSQLite3DB新建数据库、创建表、插入删除更新记录、使用事务、查询记录等等。

[cpp] view plaincopy
  1. #define SQLITE3_FILE_NAME TEXT("sqlite.db3")  
  2.   
  3. // 获取程序当前路径  
  4. void GetCurrentDirectory(CString &szPath)  
  5. {  
  6.     TCHAR buf[256] = {0};  
  7.     GetModuleFileName(NULL, buf, sizeof(buf)/sizeof(TCHAR));  
  8.     szPath = buf;         
  9.     szPath = szPath.Left(szPath.ReverseFind('\\') + 1);  
  10. }  
  11.   
  12. CString strDbPath;  
  13. GetCurrentDirectory(strDbPath);  
  14. strDbPath += SQLITE3_FILE_NAME;  
  15.   
  16. CppSQLite3DB db;  
  17.   
  18. try  
  19. {  
  20.     // 打开或新建一个数据库  
  21.     db.open(strDbPath);   
  22.   
  23.     // 判断表名是否已经存在  
  24.     if(!db.tableExists(TEXT("Customers")))   
  25.     {  
  26.         // 不存在,新建表Customers  
  27.          db.execDML(TEXT("CREATE TABLE Customers(cust_name varchar(50) NOT NULL PRIMARY KEY, cust_address varchar(50));"));  
  28.     }  
  29.   
  30.     // 插入1条记录  
  31.     db.execDML(TEXT("INSERT INTO Customers VALUES('Village Toys', '200 Maple Lane');"));  
  32.     // 插入1条记录  
  33.     db.execDML(TEXT("INSERT INTO Customers VALUES('Kids Place', '333 South Lake Drive');"));  
  34.   
  35.     // 删除1条记录  
  36.     db.execDML(TEXT("DELETE FROM Customers WHERE cust_name = 'Village Toys';"));  
  37.   
  38.     // 使用显示事务插入10条记录  
  39.     TCHAR buf[256] = {0};  
  40.     db.execDML(TEXT("BEGIN TRANSACTION;"));  
  41.     for (int i = 0; i < 10; ++i)  
  42.     {  
  43.         memset(buf, 0, sizeof(buf));  
  44.         wsprintf(buf, TEXT("INSERT INTO Customers VALUES ('Fun%dALL', '%d Sunny Place');"), i, i);  
  45.         db.execDML(buf);  
  46.     }  
  47.     db.execDML(TEXT("COMMIT TRANSACTION;"));  
  48.   
  49.     // 更新1条记录  
  50.     db.execDML(TEXT("UPDATE Customers SET cust_address = '4545 53rd Street' WHERE cust_name = 'Fun0ALL';"));  
  51.   
  52.     // 获取总记录条数  
  53.     int nCount = db.execScalar(TEXT("SELECT COUNT(*) FROM Customers;"));  
  54.     TCHAR szCount[50] = {0};  
  55.     memset(szCount, 0, sizeof(szCount));  
  56.     wsprintf(szCount, TEXT("Record count: %d."), nCount);  
  57.     AfxMessageBox(szCount);  
  58.   
  59.     // 获取每一条记录  
  60.     CppSQLite3Query q = db.execQuery(TEXT("SELECT * FROM Customers;"));  
  61.     while (!q.eof())  
  62.     {  
  63.         AfxMessageBox(q.fieldValue(0));  
  64.         q.nextRow();  
  65.     }  
  66.   
  67.     // 销毁语句  
  68.     q.finalize();  
  69.   
  70.     // 关闭数据库  
  71.     db.close();  
  72.     AfxMessageBox(TEXT("测试完成!"));  
  73. }  
  74. catch(CppSQLite3Exception ex)  
  75. {  
  76.     AfxMessageBox(ex.errorMessage());  
  77. }  

(4)

  CppSQLite3U封装了4个类:CppSQLite3Exception、CppSQLite3DB、CppSQLite3Statement、CppSQLite3Query

a) CppSQLite3Exception用于捕捉异常,errorCode以整数类形返回错误码,errorMessageUnicode字符串类型返回错误码。

[cpp] view plaincopy
  1. class CppSQLite3Exception  
  2. {  
  3. public:  
  4.     … …  
  5.     const int errorCode() { return mnErrCode; }  
  6.     LPCTSTR errorMessage() { return mpszErrMess; }  
  7.     static LPCTSTR  errorCodeAsString(int nErrCode);  
  8.     … …  
  9. };  

通常用法如:

[cpp] view plaincopy
  1. try  
  2. {  
  3.     … …      
  4. }  
  5. catch(CppSQLite3Exception ex)  
  6. {  
  7.   
  8.     AfxMessageBox(ex.errorMessage());  
  9. }  

b) CppSQLite3DB用于新建数据库,打开关闭数据库连接,执行DML、DDL,检索数据等。如:open打开数据库连接,close关闭数据库连接,tableExists检查某表是否存在,execDML执行SQL命令,execQuery检索记录,setBusyTimeout设置SQLite内部的busy handler的超时时间,SQLiteVersion返回SQLite版本。

[cpp] view plaincopy
  1. class CppSQLite3DB   
  2. {  
  3. public:      
  4.     … …  
  5.     void open(LPCTSTR szFile);  
  6.     void close();  
  7.     bool tableExists(LPCTSTR szTable);  
  8.     int execDML(LPCTSTR szSQL);  
  9.     CppSQLite3Query execQuery(LPCTSTR szSQL);  
  10.     int execScalar(LPCTSTR szSQL);  
  11.     CString execScalarStr(LPCTSTR szSQL);  
  12.     CppSQLite3Statement compileStatement(LPCTSTR szSQL);  
  13.     sqlite_int64 lastRowId();  
  14.     void interrupt() { sqlite3_interrupt(mpDB); }      
  15.     void setBusyTimeout(int nMillisecs);  
  16.     static const char* SQLiteVersion() { return SQLITE_VERSION; }  
  17.     … …  
  18. };  

c) CppSQLite3Statement也可以执行SQL命令,它最大的特点是支持参数绑定。对于参数绑定的用处,参考“SQlite数据库的C编程接口(四) 绑定参数(Bound Parameters) ——《Using SQlite》读书笔记”学习。该类导出的接口函数中,bind用于给SQL语句中的参数绑定指定的值,reset函数用于重置SQL语句,finalize用于销毁语句。

[cpp] view plaincopy
  1. class CppSQLite3Statement  
  2. {  
  3. public:  
  4.     … …  
  5.     CppSQLite3Statement& operator=(const CppSQLite3Statement& rStatement);  
  6.     int execDML();  
  7.     CppSQLite3Query execQuery();  
  8.     void bind(int nParam, LPCTSTR szValue);  
  9.     void bind(int nParam, const int nValue);  
  10.     void bind(int nParam, const double dwValue);  
  11.     void bind(int nParam, const unsigned char* blobValue, int nLen);  
  12.     void bindNull(int nParam);  
  13.     void reset();  
  14.     void finalize();  
  15.     … …  
  16. };  

用法如:

[cpp] view plaincopy
  1. try  
  2. {  
  3.     CppSQLite3DB db;  
  4.     db.execDML("CREATE TABLE emp(empno int, empname char(20));");  
  5.     db.execDML("BEGIN TRANSACTION;");  
  6.     CppSQLite3Statement stmt = db.compileStatement("INSERT INTO emp VALUES (:empno, : empname);");  
  7.     for (i = 0; i < nRowsToCreate; ++i)  
  8.     {  
  9.         char buf[16];  
  10.         sprintf(buf, "EmpName%06d", i);  
  11.         stmt.bind(":empno", i);  
  12.         stmt.bind(":empname ", buf);  
  13.         stmt.execDML();  
  14.         stmt.reset();  
  15.     }  
  16.     db.execDML("COMMIT TRANSACTION; ");  
  17. }  
  18. catch (CppSQLite3Exception& e)  
  19. {  
  20.     cerr << e.errorCode() << ":" << e.errorMessage() << endl;  
  21. }  

d) CppSQLite3Query用于检索记录并读出结果。它导出的public接口函数大多都是SQLite3C API _sqlite3_column_xxx函数的封装,通过该API函数读取结果集中某一行的某一列。nextRow函数用于检索下一行,eof用于判断是否到结果集的结尾。

[cpp] view plaincopy
  1. class CppSQLite3Query  
  2. {  
  3. public:  
  4.     … ….  
  5.     int numFields();  
  6.     int fieldIndex(LPCTSTR szField);  
  7.     LPCTSTR fieldName(int nCol);  
  8.     LPCTSTR fieldDeclType(int nCol);  
  9.     int fieldDataType(int nCol);  
  10.     LPCTSTR fieldValue(int nField);  
  11.     LPCTSTR fieldValue(LPCTSTR szField);  
  12.     int getIntField(int nField, int nNullValue=0);  
  13.     int getIntField(LPCTSTR szField, int nNullValue=0);  
  14.     double getFloatField(int nField, double fNullValue=0.0);  
  15.     double getFloatField(LPCTSTR szField, double fNullValue=0.0);  
  16.     LPCTSTR getStringField(int nField, LPCTSTR szNullValue=_T(""));  
  17.     LPCTSTR getStringField(LPCTSTR szField, LPCTSTR szNullValue=_T(""));  
  18.     const unsigned char* getBlobField(int nField, int& nLen);  
  19.     const unsigned char* getBlobField(LPCTSTR szField, int& nLen);  
  20.     bool fieldIsNull(int nField);  
  21.     bool fieldIsNull(LPCTSTR szField);  
  22.     bool eof();  
  23.     void nextRow();  
  24.     void finalize();  
  25.     … …   
  26. };  

SQLite3数据库Native C++封装类(Unicode)CppSQLite3U的初步认识与使用

0 0
原创粉丝点击