sqlite的API可参考:SQLite -- C/C++ | 菜鸟教程
sqlite的官网API可参考:Introduction
cpp
#include <iostream>
#include <sqlite3.h>
#include <string>
// 回调函数,用于查询结果的输出
static int callback(void* data, int argc, char** argv, char** azColName) {
// 第一次调用时输出表名
static bool firstCall = true;
static std::string tableName = reinterpret_cast<const char*>(data);
if (firstCall) {
std::cout << "\n表名: " << tableName << std::endl;
std::cout << "--------------------------------" << std::endl;
// 输出列名
for (int i = 0; i < argc; i++) {
std::cout << azColName[i] << "\t";
}
std::cout << "\n--------------------------------" << std::endl;
firstCall = false;
}
// 输出数据行
for (int i = 0; i < argc; i++) {
std::cout << (argv[i] ? argv[i] : "") << "\t";
}
std::cout << std::endl;
return 0;
}
int main() {
sqlite3* db;
char* errMsg = nullptr;
int rc;
// 1. 打开或创建数据库
rc = sqlite3_open("demo.db", &db);
if (rc) {
std::cerr << "无法打开数据库: " << sqlite3_errmsg(db) << std::endl;
return rc;
}
std::cout << "成功打开/创建数据库 demo.db" << std::endl;
// 2. 创建表
const char* createTableSQL =
"CREATE TABLE IF NOT EXISTS Users ("
"ID INTEGER PRIMARY KEY AUTOINCREMENT,"
"Name TEXT NOT NULL,"
"Age INTEGER,"
"Email TEXT UNIQUE NOT NULL);";
rc = sqlite3_exec(db, createTableSQL, nullptr, nullptr, &errMsg);
printf("%s\n",createTableSQL);
if (rc != SQLITE_OK) {
std::cerr << "SQL错误: " << errMsg << std::endl;
sqlite3_free(errMsg);
} else {
std::cout << "表 Users 创建成功或已存在" << std::endl;
}
// 3. 插入数据
const char* insertDataSQL =
"INSERT INTO Users (Name, Age, Email) VALUES "
"('张三', 25, 'zhangsan@example.com'),"
"('李四', 30, 'lisi@example.com'),"
"('王五', 28, 'wangwu@example.com');";
rc = sqlite3_exec(db, insertDataSQL, nullptr, nullptr, &errMsg);
if (rc != SQLITE_OK) {
std::cerr << "SQL错误: " << errMsg << std::endl;
sqlite3_free(errMsg);
} else {
std::cout << "成功插入 3 条数据到 Users 表" << std::endl;
}
// 4. 查询数据
std::string tableName = "Users";
const char* selectDataSQL = "SELECT * FROM Users;";
std::cout << "\n正在查询数据..." << std::endl;
rc = sqlite3_exec(db, selectDataSQL, callback, const_cast<char*>(tableName.c_str()), &errMsg);
if (rc != SQLITE_OK) {
std::cerr << "SQL错误: " << errMsg << std::endl;
sqlite3_free(errMsg);
}
// 5. 关闭数据库
sqlite3_close(db);
std::cout << "\n数据库连接已关闭" << std::endl;
return 0;
}
CMake如下:
cpp
cmake_minimum_required(VERSION 3.5)
project(testDB LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(testDB main.cpp)
target_link_libraries(testDB sqlite3)
运行结果如下:

sqlite3_exec函数介绍
sqlite3_exec()
是 SQLite C 接口中的一个便捷函数,用于执行一个或多个 SQL 语句,并可选择性地处理查询结果。它是 sqlite3_prepare_v2()
、sqlite3_step()
和 sqlite3_finalize()
的封装,适合执行不需要复杂处理的 SQL 命令。
函数原型
|--------------------------------------------------|
| int sqlite3_exec(
|
| sqlite3 *db, /* 数据库连接对象 */
|
| const char *sql, /* 要执行的 SQL 语句 */
|
| int (*callback)( /* 回调函数,处理查询结果 */
|
| void*, /* 回调函数的第一个参数(由sqlite3_exec的第四个参数传入) */
|
| int, /* 结果行的列数 */
|
| char**, /* 当前行的数据数组 */
|
| char** /* 列名数组 */
|
| ),
|
| void *data, /* 传递给回调函数的第一个参数 */
|
| char **errmsg /* 错误信息(需手动释放) */
|
| );
|
参数详解
1. db
- 类型 :
sqlite3*
- 作用 : 已打开的数据库连接对象(通过
sqlite3_open()
获得)。 - 注意 : 如果为 `` 或无效连接,函数返回
SQLITE_MISUSE
。
2. sql
-
类型 :
const char*
-
作用 : 要执行的 SQL 语句,可以是单个语句或多个语句(用分号
;
分隔)。 -
示例 :
sql
|------------------------------------------------------------------|
|"CREATE TABLE test (id INTEGER); INSERT INTO test VALUES (1);"
| -
注意 :
- 如果 SQL 有语法错误,
sqlite3_exec()
会返回错误码,并通过errmsg
返回错误信息。 - 不支持参数绑定(如
?
或:name
),需直接拼接 SQL 字符串(需注意 SQL 注入风险)。
- 如果 SQL 有语法错误,
3. callback
-
类型 : 函数指针
int (*callback)(void*, int, char**, char**)
-
作用 : 处理查询结果的回调函数。对 SELECT 查询的每一行结果调用一次;对 INSERT/UPDATE/DELETE 等操作不调用(除非返回影响行数)。
-
回调函数参数 :
void* data
: 由sqlite3_exec
的第四个参数data
传入(通常用于传递上下文)。int argc
: 当前行的列数。char** argv
: 当前行的数据数组(argv[i]
是第i
列的值,字符串形式)。char** azColName
: 列名数组(azColName[i]
是第i
列的名称)。
-
返回值 :
- 返回
0
表示继续处理后续行。 - 返回非零值会中断查询,
sqlite3_exec()
会立即返回SQLITE_ABORT
。
- 返回
-
示例 :
|-----------------------------------------------------------------------------|
|static int callback(void *data, int argc, char **argv, char **colNames) {
|
|for (int i = 0; i < argc; i++) {
|
|printf("%s = %s\n", colNames[i], argv[i] ? argv[i] : "");
|
|}
|
|return 0;
|
|}
|
4. data
-
类型 :
void*
-
作用 : 传递给回调函数的第一个参数(
callback
的void* data
)。 -
用途: 通常用于传递上下文信息(如输出文件名、表名等)。
-
示例 :
|----------------------------------------------------------------------------------|
|const char* tableName = "Users";
|
|sqlite3_exec(db, "SELECT * FROM Users;", callback, (void*)tableName, &errMsg);
|
5. errmsg
-
类型 :
char**
-
作用: 指向错误信息字符串的指针。如果执行失败,SQLite 会分配错误信息(需手动释放)。
-
注意 :
- 成功时
*errmsg
为 ``。 - 失败时需调用
sqlite3_free(*errmsg)
释放内存。 - 如果传入的
errmsg
为 ``,错误信息不会被返回。
- 成功时
-
示例 :
|------------------------------------------------------------------------|
|char *errMsg = nullptr;
|
|int rc = sqlite3_exec(db, "INVALID SQL", nullptr, nullptr, &errMsg);
|
|if (rc != SQLITE_OK) {
|
|std::cerr << "Error: " << errMsg << std::endl;
|
|sqlite3_free(errMsg); // 必须释放!
|
|}
|
返回值
SQLITE_OK
(0): 执行成功。- 其他错误码 (如
SQLITE_ERROR
,SQLITE_MISUSE
): 表示执行失败,可通过errmsg
获取详情。
典型用法
1. 执行非查询语句(如 CREATE/INSERT)
|--------------------------------------------------------------|
| char *errMsg = nullptr;
|
| int rc = sqlite3_exec(db,
|
| "CREATE TABLE IF NOT EXISTS test (id INTEGER, name TEXT);"
|
| "INSERT INTO test VALUES (1, 'Alice');",
|
| nullptr, nullptr, &errMsg);
|
| |
| if (rc != SQLITE_OK) {
|
| fprintf(stderr, "SQL error: %s\n", errMsg);
|
| sqlite3_free(errMsg);
|
| }
|
2. 执行查询并处理结果
|-------------------------------------------------------------------------------|
| static int printRow(void *unused, int argc, char **argv, char **colNames) {
|
| for (int i = 0; i < argc; i++) {
|
| printf("%s: %s\n", colNames[i], argv[i] ? argv[i] : "");
|
| }
|
| printf("---\n");
|
| return 0;
|
| }
|
| |
| sqlite3_exec(db, "SELECT * FROM test;", printRow, nullptr, &errMsg);
|
注意事项
-
SQL 注入风险 :
sqlite3_exec
直接执行 SQL 字符串,避免拼接用户输入。如需参数化查询,应使用sqlite3_prepare_v2()
+sqlite3_bind_*()
。 -
错误处理 :
始终检查返回值,并释放
errmsg
(如果非)。 -
性能 :
不适合大量数据操作(每次调用会重新解析 SQL)。高频操作建议使用预处理语句(Prepared Statements)。
-
多语句执行 :
可通过分号
;
分隔多个 SQL 语句,但某条语句失败时,后续语句不会执行。
其他函数
如果需要更精细的控制(如参数绑定、事务处理),建议使用:
sqlite3_prepare_v2()
sqlite3_bind_*()
sqlite3_step()
sqlite3_finalize()
例如:
|---------------------------------------------------------------------------------|
| sqlite3_stmt *stmt;
|
| sqlite3_prepare_v2(db, "INSERT INTO test VALUES (?, ?)", -1, &stmt, nullptr);
|
| sqlite3_bind_int(stmt, 1, 2);
|
| sqlite3_bind_text(stmt, 2, "Bob", -1, SQLITE_STATIC);
|
| sqlite3_step(stmt);
|
| sqlite3_finalize(stmt);
|
sqlite的demo可参考:SQLite3 - Linux C上数据库开发(基本操作,这篇够了)_linux 上c语言使用sqlite3-CSDN博客
Sqlite3小结(小型数据库中增删改查的操作)_如何获得sqlite3库表的记录的大小-CSDN博客
参加上面的连接查看数据代码也可以写成下面代码:
cpp
//获取行数
int nrow,ncolumn;
char selectCmd[]="select * from Users;";
char **result;
if(sqlite3_get_table(db,selectCmd,&result,&nrow,&ncolumn,&errMsg)!=0)
{
std::cerr << "SQL错误: " << errMsg << std::endl;
sqlite3_free(errMsg);
}
printf("nrow is %d, ncolumn is %d\n",nrow,ncolumn);//测试输出
int i,j=0;
for(i=1;i<=nrow;i++)//result内结果包含表头信息,因此result[0]是表头信息,实际数据范围为result[1]~result[nrow]
{
for(j=0;j<ncolumn;j++)
{
printf("%s:%s\n",result[j],result[i*ncolumn+j]);
}
printf("------------------\n");
}
运行结果如下:
