zoukankan      html  css  js  c++  java
  • 自己整理的一个访问SQLite3数据库的C++类

    原文地址:自己整理的一个访问SQLite3数据库的C++类作者:vigra
    近日,对SQLite3的使用进行了研究。真不愧是优秀的嵌入数据库,API接口也极其简捷。基本上只要使用以下几个接口就能完成数据库的操作:
     
    sqlite3_open()
    sqlite3_prepare()
    sqlite3_step()
    sqlite3_column()
    sqlite3_finalize()
    sqlite3_close()
    但是,API方式不太符合数据库开发的习惯。我们是C++程序员,封装一下吧。
     
    多网上找到了一份Rob Groves在2004写的“C++ wrapper around the SQLite3 embedded database library.”基本可用,但太复杂了,不利于学习。
     
    所以,我对其进行了简化,只保留了3个类:
     
    TSQLite3Exception 用于异常处理
     
    TSQLite3Query 用于处理带返回数据的SQL语句
     
    TSQLite3DB 用于对数据库本身的操作
     
    经过这样的简化,在保证基本数据库操作的前提下,代码行数变成的原来的1/3,简捷、易用,推荐给大家。
     
    还附上一些应用示例代码,方便大家上手。我测试用的SQLite3版本是3.7.3
     
    //---------------------------------------------------------------------------
    int __fastcall TDataModule1::UpdateFounds(String sCode, String sName, String sDate, String sValue)
    {
    char SqlStr[500];
    TSQLite3DB *db;
    // open the database file
    db = new TSQLite3DB();
     
    try
    {
    try
    {
    db->open("data.s3db");
    //更新记录
    sprintf(SqlStr, "UPDATE FOUNDS SET FOUND_NAME='%s', DATE='%s', VALUE='%s' WHERE CODE='%s'",
    AnsiString(sName).c_str(), AnsiString(sDate).c_str(), AnsiString(sValue).c_str(), AnsiString(sCode).c_str());
    db->execDML(SqlStr);
    }
    catch(const TSQLite3Exception &e)
    {
    ShowMessage(String("更新记录失败!") + e.errorMessage());
    }
    catch(...)
    {
    return -1;
    }
     
    return 0;
    }
     
    __finally
    {
    delete db;
    }
    }
    //---------------------------------------------------------------------------
    int __fastcall TDataModule1::FillListViewFirst(TListView *ListView)
    {
    TListItem *pItem = NULL;
    TSQLite3DB *db;
    // open the database file
    db = new TSQLite3DB();
     
    try
    {
    try
    {
    db->open("data.s3db");
    TSQLite3Query Results = db->execQuery("SELECT * FROM FOUNDS ORDER BY CODE");
    ListView->Items->Clear();
     
    for( ; !Results.eof(); Results.nextRow())
    {
    //如果不需要显示,则跳过
    if(strncmp("是", Results.getStringField(4, ""), 2) == 0)
    {
    pItem = ListView->Items->Add();
    //第1列
    pItem->Caption = String(Results.getStringField(0, ""));
    //第2列
    pItem->SubItems->Add(Results.getStringField(1, ""));
    //第3列
    pItem->SubItems->Add(Results.getStringField(2, ""));
    //第4列
    pItem->SubItems->Add(Results.getStringField(3, ""));
    }
    }
    }
    catch(const TSQLite3Exception &e)
    {
    ShowMessage(String("查询记录失败!") + e.errorMessage());
    }
    catch(...)
    {
    return -1;
    }
     
    return 0;
    }
     
    __finally
    {
    delete db;
    }
    }
     
     
     
     
    //---------------------------------------------------------------------------
     
    #include <string.h>
    #include <time.h>
    #pragma hdrstop
     
    #include "SQLite3_unit.h"
    #pragma package(smart_init)
     
    // Named constant for passing to TSQLite3Exception when passing it a string
    // that cannot be deleted.
    static const bool DONT_DELETE_MSG = false;
    // Timeout values on busy or lock conditions
    static const int SQLTM_TIMEOUT = 6000; // 6 seconds
     
    ////////////////////////////////////////////////////////////////////////////////
     
    TSQLite3Exception::TSQLite3Exception(const int nErrCode,
    char *szErrMess,
    bool bDeleteMsg) :
    mnErrCode(nErrCode)
    {
    mpszErrMess = sqlite3_mprintf("%s[%d]: %s",
    errorCodeAsString(nErrCode),
    nErrCode,
    szErrMess ? szErrMess : "");
     
    if(bDeleteMsg && szErrMess)
    {
    sqlite3_free(szErrMess);
    }
    }
    //---------------------------------------------------------------------------
     
     
    TSQLite3Exception::TSQLite3Exception(const TSQLite3Exception &e) :
    mnErrCode(e.mnErrCode)
    {
    mpszErrMess = 0;
     
    if(e.mpszErrMess)
    {
    mpszErrMess = sqlite3_mprintf("%s", e.mpszErrMess);
    }
    }
    //---------------------------------------------------------------------------
     
     
    const char *TSQLite3Exception::errorCodeAsString(int nErrCode)
    {
    switch(nErrCode)
    {
    case SQLITE_OK :
    return "Successful result";
    case SQLITE_ERROR :
    return "SQL error or missing database";
    case SQLITE_INTERNAL :
    return "Internal logic error in SQLite ";
    case SQLITE_PERM :
    return "Access permission denied";
    case SQLITE_ABORT :
    return "Callback routine requested an abort";
    case SQLITE_BUSY :
    return "The database file is locked";
    case SQLITE_LOCKED :
    return "A table in the database is locked";
    case SQLITE_NOMEM :
    return "A malloc() failed";
    case SQLITE_READONLY :
    return "Attempt to write a readonly database";
    case SQLITE_INTERRUPT :
    return "Operation terminated by sqlite3_interrupt()";
    case SQLITE_IOERR :
    return "Some kind of disk I/O error occurred ";
    case SQLITE_CORRUPT :
    return "The database disk image is malformed";
    case SQLITE_NOTFOUND :
    return "NOT USED. Table or record not found";
    case SQLITE_FULL :
    return "Insertion failed because database is full";
    case SQLITE_CANTOPEN :
    return "Unable to open the database file";
    case SQLITE_PROTOCOL :
    return "Database lock protocol error";
    case SQLITE_EMPTY :
    return "Database is empty";
    case SQLITE_SCHEMA :
    return "The database schema changed";
    case SQLITE_TOOBIG :
    return "String or BLOB exceeds size limit";
    case SQLITE_CONSTRAINT :
    return "Abort due to constraint violation";
    case SQLITE_MISMATCH :
    return "Data type mismatch";
    case SQLITE_MISUSE :
    return "Library used incorrectly";
    case SQLITE_NOLFS :
    return "Uses OS features not supported on host";
    case SQLITE_AUTH :
    return "Authorization denied";
    case SQLITE_FORMAT :
    return "Auxiliary database format error";
    case SQLITE_RANGE :
    return "2nd parameter to sqlite3_bind out of range";
    case SQLITE_NOTADB :
    return "File opened that is not a database file";
    case SQLITE_ROW :
    return "sqlite3_step() has another row ready";
    case SQLITE_DONE :
    return "sqlite3_step() has finished executing";
    case TSQLITE_ERROR :
    return "TSQLITE_ERROR";
    default:
    return "UNKNOWN_ERROR";
    }
    }
    //---------------------------------------------------------------------------
    TSQLite3Exception::~TSQLite3Exception()
    {
    if(mpszErrMess)
    {
    sqlite3_free(mpszErrMess);
    mpszErrMess = 0;
    }
    }
    ////////////////////////////////////////////////////////////////////////////////
    //---------------------------------------------------------------------------
    TSQLite3Query::TSQLite3Query()
    {
    mpDB = 0;
    mpVM = 0;
    mbEof = true;
    mnCols = 0;
    mbOwnVM = false;
    }
    //---------------------------------------------------------------------------
    TSQLite3Query::TSQLite3Query(const TSQLite3Query &rQuery)
    {
    mpDB = rQuery.mpDB;
    mpVM = rQuery.mpVM;
    // Only one object can own the VM
    const_cast<TSQLite3Query &>(rQuery).mpVM = 0;
    mbEof = rQuery.mbEof;
    mnCols = rQuery.mnCols;
    mbOwnVM = rQuery.mbOwnVM;
    }
    //---------------------------------------------------------------------------
    TSQLite3Query::TSQLite3Query(sqlite3 *pDB,
    sqlite3_stmt *pVM,
    bool bEof,
    bool bOwnVM)
    {
    mpDB = pDB;
    mpVM = pVM;
    mbEof = bEof;
    mnCols = sqlite3_column_count(mpVM);
    mbOwnVM = bOwnVM;
    }
    //---------------------------------------------------------------------------
    TSQLite3Query::~TSQLite3Query()
    {
    try
    {
    finalize();
    }
    catch(...)
    {
    }
    }
    //---------------------------------------------------------------------------
    TSQLite3Query &TSQLite3Query::operator=(const TSQLite3Query &rQuery)
    {
    try
    {
    finalize();
    }
    catch(...)
    {
    }
     
    mpDB = rQuery.mpDB;
    mpVM = rQuery.mpVM;
    // Only one object can own the VM
    const_cast<TSQLite3Query &>(rQuery).mpVM = 0;
    mbEof = rQuery.mbEof;
    mnCols = rQuery.mnCols;
    mbOwnVM = rQuery.mbOwnVM;
    return *this;
    }
    //---------------------------------------------------------------------------
    int TSQLite3Query::numFields()
    {
    checkVM();
    return mnCols;
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::fieldValue(int nField)
    {
    checkVM();
     
    if(nField < 0 || nField > mnCols - 1)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field index requested",
    DONT_DELETE_MSG);
    }
     
    return (const char *)sqlite3_column_text(mpVM, nField);
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::fieldValue(const char *szField)
    {
    int nField = fieldIndex(szField);
    return (const char *)sqlite3_column_text(mpVM, nField);
    }
    //---------------------------------------------------------------------------
    int TSQLite3Query::getIntField(int nField, int nNullValue)
    {
    if(fieldDataType(nField) == SQLITE_NULL)
    {
    return nNullValue;
    }
    else
    {
    return sqlite3_column_int(mpVM, nField);
    }
    }
    //---------------------------------------------------------------------------
    int TSQLite3Query::getIntField(const char *szField, int nNullValue)
    {
    int nField = fieldIndex(szField);
    return getIntField(nField, nNullValue);
    }
    //---------------------------------------------------------------------------
    double TSQLite3Query::getFloatField(int nField, double fNullValue)
    {
    if(fieldDataType(nField) == SQLITE_NULL)
    {
    return fNullValue;
    }
    else
    {
    return sqlite3_column_double(mpVM, nField);
    }
    }
    //---------------------------------------------------------------------------
    double TSQLite3Query::getFloatField(const char *szField, double fNullValue)
    {
    int nField = fieldIndex(szField);
    return getFloatField(nField, fNullValue);
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::getStringField(int nField, const char *szNullValue)
    {
    if(fieldDataType(nField) == SQLITE_NULL)
    {
    return szNullValue;
    }
    else
    {
    return (const char *)sqlite3_column_text(mpVM, nField);
    }
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::getStringField(const char *szField, const char *szNullValue)
    {
    int nField = fieldIndex(szField);
    return getStringField(nField, szNullValue);
    }
    //---------------------------------------------------------------------------
    const unsigned char *TSQLite3Query::getBlobField(int nField, int &nLen)
    {
    checkVM();
     
    if(nField < 0 || nField > mnCols - 1)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field index requested",
    DONT_DELETE_MSG);
    }
     
    nLen = sqlite3_column_bytes(mpVM, nField);
    return (const unsigned char *)sqlite3_column_blob(mpVM, nField);
    }
    //---------------------------------------------------------------------------
    const unsigned char *TSQLite3Query::getBlobField(const char *szField, int &nLen)
    {
    int nField = fieldIndex(szField);
    return getBlobField(nField, nLen);
    }
    //---------------------------------------------------------------------------
    bool TSQLite3Query::fieldIsNull(int nField)
    {
    return (fieldDataType(nField) == SQLITE_NULL);
    }
    //---------------------------------------------------------------------------
    bool TSQLite3Query::fieldIsNull(const char *szField)
    {
    int nField = fieldIndex(szField);
    return (fieldDataType(nField) == SQLITE_NULL);
    }
    //---------------------------------------------------------------------------
    int TSQLite3Query::fieldIndex(const char *szField)
    {
    checkVM();
     
    if(szField)
    {
    for(int nField = 0; nField < mnCols; nField++)
    {
    const char *szTemp = sqlite3_column_name(mpVM, nField);
     
    if(strcmp(szField, szTemp) == 0)
    {
    return nField;
    }
    }
    }
     
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field name requested",
    DONT_DELETE_MSG);
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::fieldName(int nCol)
    {
    checkVM();
     
    if(nCol < 0 || nCol > mnCols - 1)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field index requested",
    DONT_DELETE_MSG);
    }
     
    return sqlite3_column_name(mpVM, nCol);
    }
    //---------------------------------------------------------------------------
    const char *TSQLite3Query::fieldDeclType(int nCol)
    {
    checkVM();
     
    if(nCol < 0 || nCol > mnCols - 1)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field index requested",
    DONT_DELETE_MSG);
    }
     
    return sqlite3_column_decltype(mpVM, nCol);
    }
    //---------------------------------------------------------------------------
    int TSQLite3Query::fieldDataType(int nCol)
    {
    checkVM();
     
    if(nCol < 0 || nCol > mnCols - 1)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Invalid field index requested",
    DONT_DELETE_MSG);
    }
     
    return sqlite3_column_type(mpVM, nCol);
    }
    //---------------------------------------------------------------------------
    bool TSQLite3Query::eof()
    {
    checkVM();
    return mbEof;
    }
    //---------------------------------------------------------------------------
    void TSQLite3Query::nextRow()
    {
    checkVM();
    int nRet = sqlite3_step(mpVM);
     
    if(nRet == SQLITE_DONE)
    {
    // no rows
    mbEof = true;
    }
    else if(nRet == SQLITE_ROW)
    {
    // more rows, nothing to do
    }
    else
    {
    nRet = sqlite3_reset(mpVM);
    mpVM = 0;
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(nRet,
    (char *)szError,
    DONT_DELETE_MSG);
    }
    }
    //---------------------------------------------------------------------------
    void TSQLite3Query::finalize()
    {
    if(mpVM && mbOwnVM)
    {
    int nRet = sqlite3_finalize(mpVM);
    mpVM = 0;
     
    if(nRet != SQLITE_OK)
    {
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(nRet, (char *)szError, DONT_DELETE_MSG);
    }
    }
    else if(mpVM && !mbOwnVM)
    {
    sqlite3_reset(mpVM);
    }
    }
    //---------------------------------------------------------------------------
    void TSQLite3Query::checkVM()
    {
    if(mpVM == 0)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Null Virtual Machine pointer",
    DONT_DELETE_MSG);
    }
    }
    ////////////////////////////////////////////////////////////////////////////////
    //---------------------------------------------------------------------------
    TSQLite3DB::TSQLite3DB()
    {
    mpDB = 0;
    mnBusyTimeoutMs = SQLTM_TIMEOUT;
    }
    //---------------------------------------------------------------------------
    TSQLite3DB::TSQLite3DB(const TSQLite3DB &db)
    {
    mpDB = db.mpDB;
    mnBusyTimeoutMs = SQLTM_TIMEOUT;
    }
    //---------------------------------------------------------------------------
    TSQLite3DB::~TSQLite3DB()
    {
    close();
    }
    //---------------------------------------------------------------------------
    TSQLite3DB &TSQLite3DB::operator=(const TSQLite3DB &db)
    {
    mpDB = db.mpDB;
    mnBusyTimeoutMs = SQLTM_TIMEOUT;
    return *this;
    }
    //---------------------------------------------------------------------------
    void TSQLite3DB::open(const char *szFile)
    {
    int nRet = sqlite3_open(szFile, &mpDB);
     
    if(nRet != SQLITE_OK)
    {
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(nRet, (char *)szError, DONT_DELETE_MSG);
    }
     
    setBusyTimeout(mnBusyTimeoutMs);
    }
    //---------------------------------------------------------------------------
    void TSQLite3DB::close()
    {
    if(mpDB)
    {
    int Result = sqlite3_close(mpDB);
     
    if(Result != SQLITE_OK)
    {
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(Result, (char *)szError, DONT_DELETE_MSG);
    }
     
    mpDB = 0;
    }
    }
    //---------------------------------------------------------------------------
    int TSQLite3DB::execDML(const char *szSQL)
    {
    checkDB();
    char *szError = 0;
    int nRet = sqlite3_exec(mpDB, szSQL, 0, 0, &szError);
     
    if(nRet == SQLITE_OK)
    {
    return sqlite3_changes(mpDB);
    }
    else
    {
    throw TSQLite3Exception(nRet, szError);
    }
    }
    //---------------------------------------------------------------------------
    TSQLite3Query TSQLite3DB::execQuery(const char *szSQL)
    {
    checkDB();
    sqlite3_stmt *pVM = compile(szSQL);
    int nRet = sqlite3_step(pVM);
     
    if(nRet == SQLITE_DONE)
    {
    // no rows
    return TSQLite3Query(mpDB, pVM, true);
    }
    else if(nRet == SQLITE_ROW)
    {
    // at least 1 row
    return TSQLite3Query(mpDB, pVM, false);
    }
    else
    {
    nRet = sqlite3_finalize(pVM);
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(nRet, (char *)szError, DONT_DELETE_MSG);
    }
    }
    //---------------------------------------------------------------------------
    sqlite_int64 TSQLite3DB::lastRowId()
    {
    return sqlite3_last_insert_rowid(mpDB);
    }
    //---------------------------------------------------------------------------
    void TSQLite3DB::setBusyTimeout(int nMillisecs)
    {
    mnBusyTimeoutMs = nMillisecs;
    sqlite3_busy_timeout(mpDB, mnBusyTimeoutMs);
    }
    //---------------------------------------------------------------------------
    void TSQLite3DB::checkDB()
    {
    if(!mpDB)
    {
    throw TSQLite3Exception(TSQLITE_ERROR,
    "Database not open",
    DONT_DELETE_MSG);
    }
    }
    //---------------------------------------------------------------------------
    sqlite3_stmt *TSQLite3DB::compile(const char *szSQL)
    {
    checkDB();
    const char *szTail = 0;
    sqlite3_stmt *pVM;
    int nRet;
    nRet = sqlite3_prepare_v2(mpDB, szSQL, -1, &pVM, &szTail);
     
    if(nRet != SQLITE_OK)
    {
    const char *szError = sqlite3_errmsg(mpDB);
    throw TSQLite3Exception(nRet,
    (char *)szError,
    DONT_DELETE_MSG);
    }
     
    return pVM;
    }
    //---------------------------------------------------------------------------
     
     
    //---------------------------------------------------------------------------
     
    #ifndef SQLite3_unitH
    #define SQLite3_unitH
     
    #include "sqlite3.h"
     
    #define TSQLITE_ERROR 1000
     
    //---------------------------------------------------------------------------
    class TSQLite3Exception
    {
    public:
     
    TSQLite3Exception(const int nErrCode,
    char *szErrMess,
    bool bDeleteMsg = true);
     
    TSQLite3Exception(const TSQLite3Exception &e);
     
    virtual ~TSQLite3Exception();
     
    int errorCode() const
    {
    return mnErrCode;
    }
     
    char *errorMessage() const
    {
    return mpszErrMess;
    }
     
    static const char *errorCodeAsString(int nErrCode);
     
    private:
     
    int mnErrCode;
    char *mpszErrMess;
    };
    //---------------------------------------------------------------------------
    class TSQLite3Query
    {
    public:
     
    TSQLite3Query();
     
    TSQLite3Query(const TSQLite3Query &rQuery);
     
    TSQLite3Query(sqlite3 *pDB,
    sqlite3_stmt *pVM,
    bool bEof,
    bool bOwnVM = true);
     
    TSQLite3Query &operator=(const TSQLite3Query &rQuery);
     
    virtual ~TSQLite3Query();
     
    int numFields();
     
    int fieldIndex(const char *szField);
    const char *fieldName(int nCol);
     
    const char *fieldDeclType(int nCol);
    int fieldDataType(int nCol);
     
    const char *fieldValue(int nField);
    const char *fieldValue(const char *szField);
     
    int getIntField(int nField, int nNullValue = 0);
    int getIntField(const char *szField, int nNullValue = 0);
     
    double getFloatField(int nField, double fNullValue = 0.0);
    double getFloatField(const char *szField, double fNullValue = 0.0);
     
    const char *getStringField(int nField, const char *szNullValue = "");
    const char *getStringField(const char *szField, const char *szNullValue = "");
     
    const unsigned char *getBlobField(int nField, int &nLen);
    const unsigned char *getBlobField(const char *szField, int &nLen);
     
    bool fieldIsNull(int nField);
    bool fieldIsNull(const char *szField);
     
    bool eof();
    void nextRow();
    void finalize();
     
    private:
     
    void checkVM();
     
    sqlite3 *mpDB;
    sqlite3_stmt *mpVM;
    bool mbEof;
    int mnCols;
    bool mbOwnVM;
    };
    //---------------------------------------------------------------------------
    class TSQLite3DB
    {
    public:
    TSQLite3DB();
    virtual ~TSQLite3DB();
    void open(const char *szFile);
    void close();
    int execDML(const char *szSQL);
    TSQLite3Query execQuery(const char *szSQL);
    void setBusyTimeout(int nMillisecs);
    sqlite_int64 lastRowId();
     
    void interrupt()
    {
    sqlite3_interrupt(mpDB);
    }
     
    bool isAutoCommit()
    {
    return sqlite3_get_autocommit(mpDB) != 0;
    }
     
    static const char *SQLiteVersion()
    {
    return SQLITE_VERSION;
    }
     
    sqlite3 *getDB()
    {
    return mpDB;
    }
    private:
     
    TSQLite3DB(const TSQLite3DB &db);
    TSQLite3DB &operator=(const TSQLite3DB &db);
     
    sqlite3_stmt *compile(const char *szSQL);
     
    void checkDB();
     
    sqlite3 *mpDB;
    int mnBusyTimeoutMs;
    };
     
    //---------------------------------------------------------------------------
     
    #endif
     
     
     
  • 相关阅读:
    SQL Server 2005 镜像构建说明(转载)
    表变量 vs. 临时表
    SQL Server日志
    MDX常见计算方法(百分比/分配/平均值/基于时间的计算)
    MDX中一些边界问题的处理
    MDX中的Where vs. Subselect/Subcube
    MDX优化Set操作
    SSIS处理导入数据时, 存在的更新, 不存在的插入(转载)
    MDX实现同比和环比
    iPhone4S出现应用无法打开时的解决方案
  • 原文地址:https://www.cnblogs.com/blogpro/p/11426881.html
Copyright © 2011-2022 走看看