windows下sqlite的使用

下载:

下载地址:http://www.sqlite.org/download.html

在windows平台进行开发,需要下载以下文件(版本可能不同):
sqlite-dll-win64-x64-3330000.zip
sqlite-tools-win32-x86-3330000.zip
sqlite-amalgamation-3330000.zip

准备头文件和库文件:

创建sqlite3目录,在sqlite3下创建include子目录,用于收集头文件,在sqlite3下创建lib子目录,用于收集库文件。

解压sqlite-amalgamation-3330000.zip,得到源码,拷贝其中的*.h文件到sqlite3\include。
解压sqlite-dll-win64-x64-3330000.zip,得到sqlite3.dll和sqlite3.def文件,拷贝它们到sqlite3\lib。

由于缺少sqlite3.lib文件,VS应用程序将无法链接sqlite库,可用以下的方法生成:

首先,必须确保系统已经安装VS开发工具,然后在操作系统查找栏那里搜索”命令提示”,找到对应的控制台工具,如”Visual Studio 2008 命令提示“,点击进入命令输入状态。
然后,在命令提示符下,输入cd命令切换到sqlite3\lib目录,并执行命令:lib /DEF:sqlite3.def /MACHINE:X64,这时会提示生成sqlite3.lib和sqlite3.exp文件,可以在sqlite3\lib目录下进行确认。

了解命令工具用法:

解压sqlite-tools-win32-x86-3330000.zip,得到3个可执行文件,双击运行其中的sqlite3.exe,进入命令提示符,下面举例几个简单的用法。

创建或打开数据库:
.open test.db

查看当前库存在的数据表:
.tables

创建表:
CREATE TABLE "tbtest" (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(32) NOT NULL
);

插入记录:
insert into tbtest(id,name) values(null, "aaa");

查询记录:
select * from tbtest;

可以看到有两种语法风格,以.开头的表示sqlite3命令语法 和 以;结尾的SQL命令语法。具体这里不再过多说明,请读者去百度搜索更详细和权威的资料。

了解程序API用法:

主要是连接、断开、查询(SELECT)、执行(INSERT、UPDATE),先分开来看。

连接:
sqlite3 *pDB = NULL;
int rc = sqlite3_open("./test.db", &pDB);
if (rc != 0)
    return false;

断开:
if (pDB)
{
    sqlite3_close(pDB);
    pDB = NULL;
}

查询:
char *pErrMsg = NULL;
int rc = sqlite3_exec(pDB, “select * from tbtest”, callBack4selectSQL, NULL, &pErrMsg);
if (rc != 0)
{
    sqlite3_free(pErrMsg);
}

因为查询的结果是以回调的方式给出的,留意sqlite3_exec的第3、4个参数,分别表示回调的函数名和上下文传参,我这里定义一个简单的回调函数,暂时没有使用上下文,sqlite3_exec内部每查到一行回调一次:

int callBack4selectSQL(void* pParam, int argc, char ** argv, char ** szColName)
{
    for (int i = 0; i < argc; ++i)
    {
        if (argv[i] != NULL)
        {
            printf("%s : %s \n", szColName[i], argv[i]);
        }
    }
    return 0;
}

执行:
char *pErrMsg = NULL;
int rc = sqlite3_exec(pDB, “insert into tbtest(id,name) values(null,\”aaa\”);”, NULL, NULL, &pErrMsg);
if (rc != 0)
{
    sqlite3_free(pErrMsg);
}

封装类:

在实际的软件工程中,考虑到代码的复用和可维护性,还是需要对sqlite进行适当的封装的。这里,我贴出一个,方便大家复用。在这个例子中,有实现初使化时自动检测数据表是否存在,不存在则创建的逻辑,这里需要大家根据自己的情况做适当修改。

头文件,请保存文件名为sqlitewrap.h

#pragma once

#include
#include
#include

// SQLite操作封装
class CSQLiteWrap
{
public:

    // 单例
    static CSQLiteWrap* getInstance();

    explicit CSQLiteWrap(const std::string& strDB);
    virtual ~CSQLiteWrap();

    // 执行SQL
    int excuteSQL(const std::string& strSQL, std::string& strErrMsg);

    // 查询SQL
    typedef std::pair FIELD_t;
    typedef std::vector ROW_t;
    typedef std::vector ROWS_t;
    int selectSQL(const std::string& strSQL, ROWS_t& rows, std::string& strErrMsg);

private:

    // 连接数据库
    bool __connectDB();

    // 关闭数据库
    void __disConnectDB();

    // 初使化表格
    bool __initTables();

    // 检查表格是否存在
    bool __checkTable(const std::string& strTable, bool &isExist);

    // 创建表格
    bool __createTable(const std::string& strSQL);

    // 查询SQL的回调
    static int __callBack4selectSQL(void* pParam, int argc, char ** argv, char ** szColName);

private:
    std::string m_strDB;
    bool m_bConnected;
    bool m_bInited;
    sqlite3 *m_pDB;
};

实现文件,请保存文件名为sqlitewrap.cpp

#include "sqlitewrap.h"

#include
#include "helper.h"

#define SQLITE_DBNAME "./test.db"

// 单例
CSQLiteWrap* CSQLiteWrap::getInstance()
{
    static CSQLiteWrap* g_pSQLiteWrap = NULL;

    if (g_pSQLiteWrap == NULL)
    {
        g_pSQLiteWrap = new CSQLiteWrap(SQLITE_DBNAME);
    }

    return g_pSQLiteWrap;
}

CSQLiteWrap::CSQLiteWrap(const std::string& strDB)
: m_strDB(strDB)
, m_bConnected(false)
, m_bInited(false)
, m_pDB(NULL)
{
    m_bConnected = __connectDB();
    m_bInited = __initTables();
}

CSQLiteWrap::~CSQLiteWrap()
{
    __disConnectDB();
}

// 执行SQL
int CSQLiteWrap::excuteSQL(const std::string& strSQL, std::string& strErrMsg)
{
    if (!m_bInited)
        return -1;

    char *pErrMsg = NULL;
    int rc = sqlite3_exec(m_pDB, strSQL.c_str(), NULL, NULL, &pErrMsg);
    if (rc != 0)
    {
        strErrMsg = pErrMsg;
        sqlite3_free(pErrMsg);
    }

    return rc;
}

// 查询SQL
int CSQLiteWrap::selectSQL(const std::string& strSQL, CSQLiteWrap::ROWS_t& rows, std::string& strErrMsg)
{
    if (!m_bInited)
        return -1;

    char *pErrMsg = NULL;
    int rc = sqlite3_exec(m_pDB, strSQL.c_str(), __callBack4selectSQL, (void*)&rows, &pErrMsg);
    if (rc != 0)
    {
        strErrMsg = pErrMsg;
        sqlite3_free(pErrMsg);
    }

    return rc;
}

// 连接数据库
bool CSQLiteWrap::__connectDB()
{
    int rc = sqlite3_open(m_strDB.c_str(), &m_pDB);
    if (rc != 0)
    {
        OutputDebugStringA(CFuncHelper::toString("@CSQLiteWrap::__connectDB Can't open database:[%s]", m_strDB.c_str()).c_str());
        return false;
    }

    return true;
}

// 关闭数据库
void CSQLiteWrap::__disConnectDB()
{
    if (m_bConnected && m_pDB)
    {
        sqlite3_close(m_pDB);
        m_pDB = NULL;
        m_bConnected = false;
    }
}

// 初使化表格
bool CSQLiteWrap::__initTables()
{
    if (!m_bConnected)
        return false;

    // 尝试创建用户表
    {
        bool bExist = false;
        bool bRet = __checkTable("tbUser", bExist);
        if (!bRet)
            return false;

        if (!bExist)
        {
            std::string strSQL = "CREATE TABLE \"tbUser\" ( \
                    userId INTEGER PRIMARY KEY AUTOINCREMENT, \
                    name VARCHAR(32) NOT NULL, \
                    sex INTEGER, \
                    birthday VARCHAR(32), \
                    address VARCHAR(128), \
                    tel VARCHAR(32), \
                    createTime VARCHAR(32), \
                    updateTime VARCHAR(32) \
                    );";

            bRet = __createTable(strSQL);
            if (!bRet)
                return false;
        }
    }

    // 尝试创建会话表
    {
        bool bExist = false;
        bool bRet = __checkTable("tbSession", bExist);
        if (!bRet)
            return false;

        if (!bExist)
        {
            std::string strSQL = "CREATE TABLE \"tbSession\" ( \
                    userId INTEGER NOT NULL, \
                    sessionId INTEGER NOT NULL, \
                    config TEXT NOT NULL, \
                    createTime VARCHAR(32), \
                    updateTime VARCHAR(32), \
                    PRIMARY KEY(userId, sessionId) \
                    );";

            bRet = __createTable(strSQL);
            if (!bRet)
                return false;
        }
    }

    return true;
}

// 检查表格是否存在
bool CSQLiteWrap::__checkTable(const std::string& strTable, bool &isExist)
{
    if (!m_bConnected)
        return false;

    std::string strSQL = "select * from sqlite_master where type = \"table\" and name = \"" + strTable + "\";";
    CSQLiteWrap::ROWS_t rows;
    char *pErrMsg = NULL;
    int rc = sqlite3_exec(m_pDB, strSQL.c_str(), __callBack4selectSQL, (void*)&rows, &pErrMsg);
    if (rc != 0)
    {
        OutputDebugStringA(CFuncHelper::toString("@CSQLiteWrap::__checkTable exec sql:[%s] err:[%s]", strSQL.c_str(), pErrMsg).c_str());
        sqlite3_free(pErrMsg);
        return false;
    }

    for (CSQLiteWrap::ROWS_t::iterator iterRow = rows.begin(); iterRow != rows.end(); ++iterRow)
    {
        for (CSQLiteWrap::ROW_t::iterator iterField = iterRow->begin(); iterField != iterRow->end(); ++iterField)
        {
            if (iterField->first == std::string("tbl_name") && iterField->second == strTable)
            {
                isExist = true;
                break;
            }
        }

        if (isExist)
            break;
    }

    OutputDebugStringA(CFuncHelper::toString("@CSQLiteWrap::__checkTable exec sql:[%s] ok, table isexist:[%d]", strSQL.c_str(), isExist).c_str());
    return true;
}

// 创建表格
bool CSQLiteWrap::__createTable(const std::string& strSQL)
{
    if (!m_bConnected)
        return false;

    char *pErrMsg = NULL;
    int rc = sqlite3_exec(m_pDB, strSQL.c_str(), NULL, NULL, &pErrMsg);
    if (rc != 0)
    {
        OutputDebugStringA(CFuncHelper::toString("@CSQLiteWrap::__createTable exec sql:[%s] err:[%s]", strSQL.c_str(), pErrMsg).c_str());
        sqlite3_free(pErrMsg);
        reurn false;
    }

    OutputDebugStringA(CFuncHelper::toString("@CSQLiteWrap::__createTable exec sql:[%s] ok", strSQL.c_str()).c_str());
    return true;
}

// 查询SQL的回调
int CSQLiteWrap::__callBack4selectSQL(void* pParam, int argc, char ** argv, char ** szColName)
{
    CSQLiteWrap::ROWS_t* pRows = (CSQLiteWrap::ROWS_t*)pParam;
    CSQLiteWrap::ROW_t row;

    for (int i = 0; i < argc; ++i)
    {
        if (argv[i] != NULL)
        {
        //OutputDebugStringA(CFuncHelper::toString("@CSQLiteWrap::__callBack4selectSQL %s : %s", szColName[i], argv[i]).c_str());
            row.push_back( std::make_pair(szColName[i], argv[i]) );
        }
    }

    pRows->push_back(row);
    return 0;
}

还有一个helper帮助类,头文件helper.h内容如下:

#pragma once

#include
#include

class CFuncHelper
{
public:
    static std::string toString(const char* sFormat, ...);
};

实现文件helper.cpp内容如下:

#include "helper.h"

std::string CFuncHelper::toString(const char* sFormat, ...)
{
    char sLine[1024] = { 0 };

    va_list va;
    va_start(va, sFormat);
    vsnprintf(sLine, sizeof(sLine)-1, sFormat, va);
    va_end(va);

    return std::string(sLine);
}

你可能感兴趣的:(windows下sqlite的使用)