SQLite主页:SQLite Home Page
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至2021年已经接近有21个年头,SQLite也迎来了一个版本 SQLite3 已经发布。下面介绍 SQLite3 的使用方法。
目录
2. 非回调使用sql语句查询数据库 (sqlite3_get_table)
8. 释放查询结果 (sqlite3_free_table)
一、文件准备
以下文件均从SQLite官网下载。
- sqlite-amalgamation-3380000.zip
- sqlite-dll-win64-x64-3380000.zip
二、编译静态库
本节介绍文件 sqlite3.lib 的编译方法。
1. 编译文件
- 模块定义文件:sqlite3.def
2. 编译过程
开始 --> Visual Studio 2022 --> x64 Native Tools Command Prompt for VS 2022
- 打开 sqlite3.def 文件的路径
cd /d D:\tmp-source\qt-hmi\SQL\sqlite-dll-win64-x64-3330000
- 生成 sqlite3.lib 文件
LIB /DEF:sqlite3.def /machine:X64 //64位
LIB /DEF:sqlite3.def /machine:X86 //32位
3. 拓展-当只有dll文件时
- 需要先通过 dll 文件生成 def 文件
dumpbin /exports sqlite3.dll > sqlite3.def
LIB /DEF:sqlite3.def /machine:X64 //64位
LIB /DEF:sqlite3.def /machine:X86 //32位
// OR
LIB /DEF:sqlite3.def /machine:i386 /out:sqlite3.lib
4. 文件使用说明
包含 sqlite3.h 头文件,将 sqlite3.lib 库文件链接到项目中即可。
#pragma comment (lib, "sqlite3.lib")
三、编译动态库
本节介绍编译 sqlite.dll 的方法以及编译环境的配置。
1. 编译文件
- 头文件:sqlite3.h
sqlite3ext.h - 源文件:sqlite3.c
- 模块定义文件:sqlite3.def
2. 编译环境配置
此处仅展示32位dll文件编译环境配置
- 创建 win32 项目,设置 常规 --> 配置类型 和 高级(VS2022) --> 目标文件拓展名 为 .dll
- C/C++ --> 预处理器 --> 预处理器定义 (添加)
SQLITE3_EXPORTS
SQLITE_ENABLE_RTREE
SQLITE_ENABLE_COLUMN_METADATA
SQLITE_ENABLE_FTS5
- C/C++ --> 不使用预编译头
- 链接器 --> 输入 --> 附加库依赖项 (添加) sqlite3.lib 文件
- 链接器 --> 输入 --> 模块定义文件 (添加) sqlite3.def 文件
3、文件使用说明
将编译完成的动态库和可执行程序放置同一目录下。
四、SQLite3常用函数
1. 创建/打开数据库 (sqlite3_open)
int sqlite3_open(
const char *szFilename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
功能:创建/打开数据库。
参数:szFilename:数据库路径及名称;
ppDb:数据库句柄。
返回值:执行成功返回 SQLITE_OK (值为0),否则返回其他值。
2. 非回调使用sql语句查询数据库 (sqlite3_get_table)
int sqlite3_get_table(
sqlite3 *pDb, /* An open database */
const char *szSql, /* SQL to be evaluated */
char ***pazResult, /* Results of the query */
int *pnRow, /* Number of result rows written here */
int *pnColumn, /* Number of result columns written here */
char **pzErrMsg /* Error msg written here */
);
功能:非回调执行sql语句。
参数:pDb:数据库句柄;
szSql:要执行的SQL语句;
pazResult:查询结果 (一维数组);
pnRow:查出结果数据条数 (查询结果行数);
pnColumn:查出结果包含的字段数 (查询结果列数);
pzErrMsg:程序报错时输出的错误信息。
返回值:执行成功返回 SQLITE_OK,否则返回其他值。
备注:pazResult的字段值是连续的一维数组,索引区间 [0, pnColumn-1] 内存储字段名称,从索引 pnColumn 开始,后面都存字段内容。
3. 回调执行sql语句 (sqlite3_exec)
int sqlite3_exec(
sqlite3 *pDb, /* The database on which the SQL executes */
const char *szSql, /* The SQL to be executed */
sqlite3_callback xCallback, /* Invoke this callback routine */
void *pArg, /* First argument to xCallback() */
char **pzErrMsg /* Write error messages here */
);
功能:执行零个或多个SQL 语句 (增删查改),查询的结果返回给回调函数 xCallback。
参数:pDb:数据库句柄;
szSql:待执行的SQL 语句字符串,以’\0’结尾;
xCallback:回调函数,用来处理查询结果,如果不需要回调 (比如做insert 或者delete 操作时),可以输入NULL;
pArg:要传入回调函数的指针参数,没有可以置为NULL;
paErrMsg:返回错误信息,注意是指针的指针。
返回值:执行成功返回 SQLITE_OK,否则返回其他值。
4. 回调函数 (callback)
typedef int (*sqlite3_callback)(
void *para,
int nColCount,
char **pazResult,
char **pazColName
);
功能:由用户处理查询的结果。
参数:para:从sqlite3_exec() 传入的参数指针;
nColCount:查询到的这一条记录有多少个字段(即这条记录有多少列);
pazResult:查询出来的数据都保存在这里 (char* 的一 维数组,以‘\0’结尾);
pazResultName:与 pazResult 对应,表示对应数据的字段名称。
返回值:执行成功返回 SQLITE_OK,否则返回其他值。
5. 调试数据库 (*sqlite3_errmsg)
const char *sqlite3_errmsg(sqlite3 *pDB);
功能:获取最近调用的 API 返回的错误信息 (错误信息以 UTF-8 编码返回,并在下一次调用任何SQLite API 时被自动清除)。
输入参数:pDB:打开的数据库句柄。
返回值:错误信息字符串的指针。
6. 关闭数据库 (sqlite3_close)
int sqlite3_close(sqlite3 *pDb);
功能:关闭数据库。
参数:pDb:数据库句柄。
返回值:执行成果返回 SQLITE_OK,若句柄繁忙返回 SQLITE_BUSY。
7. 释放错误信息 (sqlite3_free)
void sqlite3_free(void *pErrMsg );
功能:释放存放错误信息的内存空间。
参数:pErrMsg: 返回的错误信息。
8. 释放查询结果 (sqlite3_free_table)
void sqlite3_free_table(char ***pazResult);
参数:pazResult:查询结果 (一维数组)。
五、程序示例
下面的程序中展示了前文所述方法的具体用法。
// Win32ConsoleApp.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
using namespace std;
bool bCallbackFlag = true;
// 回调函数
static int callback(void* NotUsed, int nColCount, char** pazResult, char** pazResultName)
{
if (bCallbackFlag == true)
{
for (int nIndex = 0; nIndex < nColCount; ++nIndex)
{
printf("%s\t", pazResultName[nIndex] ? pazResultName[nIndex] : "NULL");
}
printf("\n");
printf("-----------------------\n");
bCallbackFlag = false;
}
for (int nIndex = 0; nIndex < nColCount; ++nIndex)
{
printf("%s\t", pazResult[nIndex] ? pazResult[nIndex] : "NULL");
}
printf("\n");
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
typedef struct cPerson
{
char* name;
int age;
char* sex;
} cPerson;
cPerson OfficePerson[] = {
"David", 22, "man",
"Eve", 28, "man",
"Frand", 21, "woman"
};
sqlite3 *pDb; // 数据库句柄
char *szErrMsg; // 错误信息
// 打开数据库连接
long nRet = sqlite3_open("people.db", &pDb);
assert(SQLITE_OK == nRet);
// 使用sqlite3_exec()创建表
const char *szSql = "CREATE TABLE IF NOT EXISTS person(name VARCHAR(128),"
"age INTEGER,"
"sex VARCHAR(7)"
");";
nRet = sqlite3_exec(pDb, szSql, NULL, NULL, &szErrMsg);
if (nRet != SQLITE_OK)
{
printf("%s\n", szErrMsg);
sqlite3_close(pDb);
return 1;
}
// 使用sqlite3_exec()删除字段
szSql = "DELETE FROM person;";
nRet = sqlite3_exec(pDb, szSql, NULL, NULL, &szErrMsg);
if (nRet != SQLITE_OK)
{
printf("%s\n", szErrMsg);
sqlite3_close(pDb);
return 1;
}
// 使用sqlite3_exec()插入数据
szSql = "INSERT INTO person(name,age,sex) VALUES(\"Alice\",15,\"woman\");";
nRet = sqlite3_exec(pDb, szSql, NULL, NULL, &szErrMsg);
assert(SQLITE_OK == nRet);
szSql = "INSERT INTO person(name,age,sex) VALUES(\"Bob\",18,\"man\");";
nRet = sqlite3_exec(pDb, szSql, NULL, NULL, &szErrMsg);
assert(SQLITE_OK == nRet);
szSql = "INSERT INTO person(name,age,sex) VALUES(\"Charli\",11,\"man\");";
nRet = sqlite3_exec(pDb, szSql, NULL, NULL, &szErrMsg);
assert(SQLITE_OK == nRet);
// 使用sqlite3_exec()查询数据
printf("===== query by sqlite3_exec() =====\n\n");
szSql = "SELECT name,age,sex FROM person;";
nRet = sqlite3_exec(pDb, szSql, callback, NULL, &szErrMsg);
assert(SQLITE_OK == nRet);
// 使用sqlite3_get_table()查询数据
printf("\n\n===== query by sqlite3_get_table() =====\n\n");
szSql = "SELECT name,age,sex FROM person;";
int nRow, nCol;
char **pazResult;
nRet = sqlite3_get_table(pDb, szSql, &pazResult, &nRow, &nCol, &szErrMsg);
assert(SQLITE_OK == nRet);
for (int nIndex = 0; nIndex < nCol; ++nIndex)
{
printf("%s\t", pazResult[nIndex] ? pazResult[nIndex] : "NULL");
}
printf("\n");
printf("-----------------------\n");
for (int nIndex = nCol; nIndex < (nRow+1)*nCol; ++nIndex)
{
printf("%s\t", pazResult[nIndex] ? pazResult[nIndex] : "NULL");
if ((nIndex+1)%nCol == 0)
{
printf("\n");
}
}
// 使用sqlite3_prepare_v2(), sqlite3_bind_...() 插入数据
const char* pzTail;
sqlite3_stmt* pstmt;
szSql = "INSERT INTO person(name,age,sex) VALUES(?,?,?);";
nRet = sqlite3_prepare_v2(pDb, szSql, strlen(szSql), &pstmt, &pzTail);
assert(SQLITE_OK == nRet);
for (int nIndex = 0; nIndex < sizeof(OfficePerson) / sizeof(cPerson); ++nIndex)
{
int nCol = 1;
sqlite3_bind_text(pstmt, nCol++, OfficePerson[nIndex].name, strlen(OfficePerson[nIndex].name), NULL);
sqlite3_bind_int(pstmt, nCol++, OfficePerson[nIndex].age);
sqlite3_bind_text(pstmt, nCol++, OfficePerson[nIndex].sex, strlen(OfficePerson[nIndex].sex), NULL);
sqlite3_step(pstmt);
sqlite3_reset(pstmt);
}
sqlite3_finalize(pstmt);
// 使用sqlite3_prepare_v2(), sqlite3_column_...() 查询数据
printf("\n\n====== query by sqlite3_prepare_v2() ======\n\n");
const unsigned char* pTmp;
int age;
szSql = "SELECT name,age,sex FROM person;";
nRet = sqlite3_prepare_v2(pDb, szSql, strlen(szSql), &pstmt, &pzTail);
assert(SQLITE_OK == nRet);
bool nPrintFlag = true;
while (true)
{
if (nPrintFlag == true)
{
printf("name\tage\tsex\n");
printf("-----------------------\n");
nPrintFlag = false;
}
nRet = sqlite3_step(pstmt);
if (SQLITE_DONE == nRet)
{
sqlite3_finalize(pstmt);
break;
}
if (SQLITE_ROW == nRet)
{
int nCol = 0;
pTmp = sqlite3_column_text(pstmt, nCol++);
printf("%s\t", pTmp);
age = sqlite3_column_int(pstmt, nCol++);
printf("%d\t", age);
pTmp = sqlite3_column_text(pstmt, nCol++);
printf("%s\n", pTmp);
continue;
}
printf("something error.\n");
sqlite3_finalize(pstmt);
break;
}
sqlite3_close(pDb); // 关闭数据库
return 0;
}
六、数据库管理工具介绍
本节内容源自博客园某位博主,进行简单排版。原文链接如下:SQLite可视化管理工具汇总 - Man_华 - 博客园 (cnblogs.com)
1. 免费且保持更新
截至 2012/9/14 最新版本 SQLiteSpy 1.9.1 – 28 Jul 2011
单文件,界面设计紧凑,较稳定,功能较少,创建表与添加数据均需sql语句,快捷键教方便,
作为数据浏览和修改工具极佳,视图编码为utf-8,对gbk2312显示乱码。能满足一般的应用,但没有导出数据表功能,同时只能打开一个数据库文件,不支持二进制字段编辑。
- SQLiteStudio:http://sqlitestudio.one.pl/
【推荐】开源,单文件;
更新及时,功能完善的sqlite2和sqlite3工具,视图编码支持utf8。支持导出数据格式:csv、html、plain、sql、xml。可同时打开多个数据库文件,支持查看和编辑二进制字段。
- SQLiteExpert:SQLite administration | SQLite Expert
个人免费 ,需安装;
功能非常强大,如果上述两款不能满足,就试试这个吧。
- SQLite Manager (Firefox插件):https://addons.mozilla.org/zh-cn/firefox/addon/sqlite-manager/
基本功能齐全,可以将数据表导出为sql数据格式。
2. 免费但可能已停止更新
- Sqlite3Explorer:http://www.singular.gr/sqlite/
两年未更新,截至2012/9/14最新版本 V3.04 04/12/2010;但xp下只是别gbk2312编码,界面紧凑,功能全面。
- SQLite Database Browser (作者使用):http://sqlitebrowser.sourceforge.net/
简单易用,具有基本数据库管理查询功能,并且能够导入和导出数据表,支持sql文件和csv两种方式。似乎不再更新,截至2012/9/14最新版本:Version 2.0b1 released - Based on Qt4.6 - 12/09/2009。
功能齐全,界面有多语言,带导出功能,很久未更新,只识别sqlite2,可用于sqlite2到sqlite3的转换,win xp下视图的编码为gbk2312,对utf-8显示乱码。截至2012/9/14最新版本 [0.8.3.2]大概是2007年10月份。
3. 收费版-通常功能丰富且更新及时
- Sqlite.Developer:http://www.sqlitedeveloper.com
有中文版。
- SQLite Code Factory:Database tools for MySQL, SQL Server, PostgreSQL, SQLite, Oracle, DB2, Firebird by SQL Maestro Group
非商业单用户,该公司出品了很多数据库管理工具,如同类产品 SQLite Maestro。
需安装。
- Navicat for SQLite:Navicat GUI | DB Admin Tool for MySQL, PostgreSQL, MongoDB, MariaDB, SQL Server, Oracle & SQLite client
很好用,很强大,不过价格较高,适合企业使用。