微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SQLite3数据库Native C++封装类UnicodeCppSQLite3U的初步认

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”也有几十种,常见的如:easysqlitesqlite++、Cppsqlite、CppsqliteU等等。因为我通常是在Windows CE嵌入式操作系统上开发APP,而Windows CE操作系统只支持Unicode字符集,所以今天要学习和测试的是Unicode版“C++ Wrappers”:CppsqliteU

(2)

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

(3)

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

#define sqlite3_FILE_NAME TEXT("sqlite.db3")

// 获取程序当前路径
void GetCurrentDirectory(CString &szPath)
{
    TCHAR buf[256] = {0};
    GetModuleFileName(NULL,buf,sizeof(buf)/sizeof(TCHAR));
    szPath = buf;       
    szPath = szPath.Left(szPath.ReverseFind('\\') + 1);
}

CString strDbPath;
GetCurrentDirectory(strDbPath);
strDbPath += sqlite3_FILE_NAME;

Cppsqlite3DB db;

try
{
    // 打开或新建一个数据库
    db.open(strDbPath); 

    // 判断表名是否已经存在
    if(!db.tableExists(TEXT("Customers"))) 
    {
        // 不存在,新建表Customers
         db.execDML(TEXT("CREATE TABLE Customers(cust_name varchar(50) NOT NULL PRIMARY KEY,cust_address varchar(50));"));
    }

    // 插入1条记录
    db.execDML(TEXT("INSERT INTO Customers VALUES('Village Toys','200 Maple Lane');"));
    // 插入1条记录
    db.execDML(TEXT("INSERT INTO Customers VALUES('Kids Place','333 South Lake Drive');"));

    // 删除1条记录
    db.execDML(TEXT("DELETE FROM Customers WHERE cust_name = 'Village Toys';"));

    // 使用显示事务插入10条记录
    TCHAR buf[256] = {0};
    db.execDML(TEXT("BEGIN TRANSACTION;"));
    for (int i = 0; i < 10; ++i)
    {
        memset(buf,sizeof(buf));
        wsprintf(buf,TEXT("INSERT INTO Customers VALUES ('Fun%dALL','%d Sunny Place');"),i,i);
        db.execDML(buf);
    }
    db.execDML(TEXT("COMMIT TRANSACTION;"));

    // 更新1条记录
    db.execDML(TEXT("UPDATE Customers SET cust_address = '4545 53rd Street' WHERE cust_name = 'Fun0ALL';"));

    // 获取总记录条数
    int nCount = db.execScalar(TEXT("SELECT COUNT(*) FROM Customers;"));
    TCHAR szCount[50] = {0};
    memset(szCount,sizeof(szCount));
    wsprintf(szCount,TEXT("Record count: %d."),nCount);
    AfxMessageBox(szCount);

    // 获取每一条记录
    Cppsqlite3Query q = db.execQuery(TEXT("SELECT * FROM Customers;"));
    while (!q.eof())
    {
        AfxMessageBox(q.fieldValue(0));
        q.nextRow();
    }

    // 销毁语句
    q.finalize();

    // 关闭数据库
    db.close();
    AfxMessageBox(TEXT("测试完成!"));
}
catch(Cppsqlite3Exception ex)
{
    AfxMessageBox(ex.errorMessage());
}

(4)

Cppsqlite3U封装了4个类:Cppsqlite3Exception、Cppsqlite3DB、Cppsqlite3Statement、Cppsqlite3Query

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

class Cppsqlite3Exception
{
public:
    … …
    const int errorCode() { return mnErrCode; }
    LPCTSTR errorMessage() { return mpszErrMess; }
    static LPCTSTR  errorCodeAsstring(int nErrCode);
    … …
};

通常用法如:

try
{
    … …    
}
catch(Cppsqlite3Exception ex)
{

    AfxMessageBox(ex.errorMessage());
}

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

class Cppsqlite3DB 
{
public:    
    … …
    void open(LPCTSTR szFile);
    void close();
    bool tableExists(LPCTSTR szTable);
    int execDML(LPCTSTR szsql);
    Cppsqlite3Query execQuery(LPCTSTR szsql);
    int execScalar(LPCTSTR szsql);
    CString execScalarstr(LPCTSTR szsql);
    Cppsqlite3Statement compileStatement(LPCTSTR szsql);
    sqlite_int64 lastRowId();
    void interrupt() { sqlite3_interrupt(mpDB); }    
    void setBusyTimeout(int nMillisecs);
    static const char* sqliteVersion() { return sqlITE_VERSION; }
    … …
};

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

class Cppsqlite3Statement
{
public:
    … …
    Cppsqlite3Statement& operator=(const Cppsqlite3Statement& rStatement);
    int execDML();
    Cppsqlite3Query execQuery();
    void bind(int nParam,LPCTSTR szValue);
    void bind(int nParam,const int nValue);
    void bind(int nParam,const double dwValue);
    void bind(int nParam,const unsigned char* blobValue,int nLen);
    void bindNull(int nParam);
    void reset();
    void finalize();
    … …
};

用法如:

try
{
    Cppsqlite3DB db;
    db.execDML("CREATE TABLE emp(empno int,empname char(20));");
    db.execDML("BEGIN TRANSACTION;");
    Cppsqlite3Statement stmt = db.compileStatement("INSERT INTO emp VALUES (:empno,: empname);");
    for (i = 0; i < nRowsToCreate; ++i)
    {
        char buf[16];
        sprintf(buf,"EmpName%06d",i);
        stmt.bind(":empno",i);
        stmt.bind(":empname ",buf);
        stmt.execDML();
        stmt.reset();
    }
    db.execDML("COMMIT TRANSACTION; ");
}
catch (Cppsqlite3Exception& e)
{
    cerr << e.errorCode() << ":" << e.errorMessage() << endl;
}

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

class Cppsqlite3Query
{
public:
    … ….
    int numFields();
    int fieldindex(LPCTSTR szField);
    LPCTSTR fieldName(int nCol);
    LPCTSTR fieldDeclType(int nCol);
    int fieldDataType(int nCol);
    LPCTSTR fieldValue(int nField);
    LPCTSTR fieldValue(LPCTSTR szField);
    int getIntField(int nField,int nNullValue=0);
    int getIntField(LPCTSTR szField,int nNullValue=0);
    double getFloatField(int nField,double fNullValue=0.0);
    double getFloatField(LPCTSTR szField,double fNullValue=0.0);
    LPCTSTR getStringField(int nField,LPCTSTR szNullValue=_T(""));
    LPCTSTR getStringField(LPCTSTR szField,LPCTSTR szNullValue=_T(""));
    const unsigned char* getBlobField(int nField,int& nLen);
    const unsigned char* getBlobField(LPCTSTR szField,int& nLen);
    bool fieldisNull(int nField);
    bool fieldisNull(LPCTSTR szField);
    bool eof();
    void nextRow();
    void finalize();
    … … 
};

sqlite3数据库Native C++封装类(Unicode)Cppsqlite3U的初步认识与使用 by斜风细雨QQ:253786989

原文地址:https://www.jb51.cc/sqlite/201775.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐