下载:
下载地址: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 <string>
#include <vector>
#include <sqlite3.h>// 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<std::string, std::string> FIELD_t;
typedef std::vector<FIELD_t> ROW_t;
typedef std::vector<ROW_t> 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 <windows.h>
#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 <stdarg.h>
#include <string>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);
}