简介
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中
本文章介绍在Linux环境下使用SQLite3,对于SQLite 命令的学习可以参考文章sqlite教程
安装 SQLite3 开发库
通过包管理器进行安装
bash
sudo apt-get install libsqlite3-dev
API接口
sqlite3_open
打开数据库
c
int sqlite3_open(
const char *filename, /* 数据库文件名 */
sqlite3 **ppDb /* 数据库连接对象的指针 */
);
参数说明
- *const char filename:
- 类型: const char *
- 描述: 数据库文件的路径。如果文件不存在,SQLite 会尝试创建一个新的数据库文件。
- 特殊值:
- ":memory:": 打开一个内存数据库,数据不会持久化到磁盘。
- "" (空字符串): 打开一个临时数据库文件,该文件会在关闭数据库连接时自动删除。
- **sqlite3 ppDb:
- 类型: sqlite3 **
- 描述: 指向 sqlite3* 类型的指针,用于存储数据库连接对象。如果成功打开数据库,*ppDb 将指向一个新的数据库连接对象。
返回值
- int: 返回值表示执行结果的状态码。
- SQLITE_OK: 数据库成功打开。
- SQLITE_ERROR: 通用错误。
- SQLITE_BUSY: 数据库文件被其他进程锁定。
- SQLITE_CANTOPEN: 无法打开数据库文件。
- 其他状态码: 表示其他类型的错误。
sqlite3_exec
执行 SQL 命令
c
int sqlite3_exec(
sqlite3*, /* 数据库连接 */
const char *sql, /* 要执行的 SQL 语句 */
sqlite_callback, /* 回调函数 */
void *data, /* 传递给回调函数的数据 */
char **errmsg /* 错误消息 */
);
参数说明
- sqlite3*:
- 类型: sqlite3*
- 描述: 数据库连接对象的指针。这个对象是由 sqlite3_open 或 sqlite3_open_v2 函数打开数据库时返回的。
- *const char sql:
- 类型: const char *
- 描述: 要执行的 SQL 语句字符串。这个字符串可以包含一个或多个 SQL 语句,用分号分隔。
- sqlite_callback:
-
类型: sqlite_callback
-
描述: 回调函数指针。当 SQL 语句返回结果集时,这个回调函数会被调用。回调函数的原型如下:
int callback(void *data, int argc, char **argv, char **azColName);
- void *data: 传递给回调函数的用户数据指针。
- int argc: 结果集中列的数量。
- char **argv: 结果集中每一列的值。argv[0] 是第一列的值,argv[1] 是第二列的值,依此类推。
- char **azColName: 结果集中每一列的名称。azColName[0] 是第一列的名称,azColName[1] 是第二列的名称,依此类推。
-
注意: 如果 SQL 语句不返回结果集(例如 INSERT, UPDATE, DELETE 等),回调函数不会被调用。
-
- *void data:
- 类型: void *
- 描述: 传递给回调函数的用户数据指针。这个指针可以在回调函数中使用,以便在回调函数中访问外部数据。
- **char errmsg:
- 类型: char **
- 描述: 如果 SQL 语句执行失败,错误消息将存储在这个指针指向的字符串中。调用者需要负责释放这个字符串的内存,使用 sqlite3_free 函数。
- 注意: 如果 SQL 语句执行成功,*errmsg 将被设置为 NULL
返回值
- int: 返回值表示执行结果的状态码。
- SQLITE_OK: SQL 语句成功执行。
- SQLITE_ERROR: SQL 语句执行失败。
- 其他状态码: 表示其他类型的错误(例如 SQLITE_BUSY, SQLITE_MISUSE 等)。
sqlite3_close
关闭数据库
c
int sqlite3_close(
sqlite3 *db /* 数据库连接对象 */
);
参数说明
- *sqlite3 db:
- 类型: sqlite3 *
- 描述: 要关闭的数据库连接对象的指针。这个对象是由 sqlite3_open 或 sqlite3_open_v2 函数打开数据库时返回的。
返回值
- int: 返回值表示执行结果的状态码。
- SQLITE_OK: 数据库成功关闭。
- SQLITE_BUSY: 有未完成的事务或语句正在使用数据库连接。
- 其他状态码: 表示其他类型的错误。
举例说明
创建表
c
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char* argv[])
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
/* Open database */
rc = sqlite3_open("test.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
fprintf(stdout, "Opened database successfully\n");
}
/* Create SQL statement */
sql = "CREATE TABLE COMPANY(" \
"ID INT PRIMARY KEY NOT NULL," \
"NAME TEXT NOT NULL," \
"AGE INT NOT NULL," \
"ADDRESS CHAR(50)," \
"SALARY REAL );";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "Table created successfully\n");
}
sqlite3_close(db);
return 0;
}
插入表
c
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char* argv[])
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
/* Open database */
rc = sqlite3_open("test.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
fprintf(stderr, "Opened database successfully\n");
}
/* Create SQL statement */
sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
"VALUES (1, 'Paul', 32, 'California', 20000.00 ); " \
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
"VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); " \
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
"VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );" \
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
"VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "Records created successfully\n");
}
sqlite3_close(db);
return 0;
}
显示
c
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
static int callback(void *data, int argc, char **argv, char **azColName){
int i;
fprintf(stderr, "%s: ", (const char*)data);
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char* argv[])
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
const char* data = "Callback function called";
/* Open database */
rc = sqlite3_open("test.db", &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
fprintf(stderr, "Opened database successfully\n");
}
/* Create SQL statement */
sql = "SELECT * from COMPANY";
/* Execute SQL statement */
rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
if( rc != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}else{
fprintf(stdout, "Operation done successfully\n");
}
sqlite3_close(db);
return 0;
}
限制显示表数据并且使用cJson打印数据
c
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <cjson/cJSON.h>
#include <string.h>
static int callback(void *data, int argc, char **argv, char **azColName) {
cJSON *root = (cJSON *)data;
cJSON *item = cJSON_CreateObject();
for (int i = 0; i < argc; i++) {
if (strcmp(azColName[i], "ID") == 0) {
cJSON_AddNumberToObject(item, "id", atoi(argv[i]));
} else if (strcmp(azColName[i], "NAME") == 0) {
cJSON_AddStringToObject(item, "name", argv[i]);
} else if (strcmp(azColName[i], "AGE") == 0) {
cJSON_AddNumberToObject(item, "age", atoi(argv[i]));
} else if (strcmp(azColName[i], "ADDRESS") == 0) {
cJSON_AddStringToObject(item, "address", argv[i]);
} else if (strcmp(azColName[i], "SALARY") == 0) {
cJSON_AddNumberToObject(item, "salary", atof(argv[i]));
}
}
cJSON_AddItemToArray(root, item);
return 0;
}
// 回调函数来获取总条数
static int count_callback(void *data, int argc, char **argv, char **azColName) {
int *count = (int *)data;
*count = atoi(argv[0]);
return 0;
}
int main(int argc, char* argv[]) {
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql;
cJSON *root = cJSON_CreateObject();
cJSON *data_array = cJSON_CreateArray();
// 默认值
int limit = 10; // 每页显示的条数
int offset = 0; // 偏移量
// 从命令行参数中读取 limit 和 offset
if (argc > 1) {
limit = atoi(argv[1]);
}
if (argc > 2) {
offset = atoi(argv[2]);
}
/* Open database */
rc = sqlite3_open("test.db", &db);
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
} else {
fprintf(stderr, "Opened database successfully\n");
}
/* 获取总条数 */
sql = "SELECT COUNT(*) FROM COMPANY";
int total_count = 0;
rc = sqlite3_exec(db, sql, count_callback, &total_count, &zErrMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
sqlite3_close(db);
cJSON_Delete(root);
return 1;
}
/* Create SQL statement with pagination */
char sql_buffer[256];
snprintf(sql_buffer, sizeof(sql_buffer), "SELECT * FROM COMPANY LIMIT %d OFFSET %d", limit, offset);
sql = sql_buffer;
/* Execute SQL statement */
cJSON_AddItemToObject(root, "data", data_array);
rc = sqlite3_exec(db, sql, callback, data_array, &zErrMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
// 添加总条数到 JSON 输出
cJSON_AddNumberToObject(root, "total", total_count);
cJSON_AddNumberToObject(root, "limit", limit);
cJSON_AddNumberToObject(root, "offset", offset);
char *json_string = cJSON_Print(root);
fprintf(stdout, "JSON data: %s\n", json_string);
cJSON_free(json_string);
}
sqlite3_close(db);
cJSON_Delete(root);
return 0;
}
编译和执行
-
编译
bashgcc -o view view.c -lcjson -lsqlite3
-
执行
c./view 10 0
打印结果
bash
{
"data": [
{
"id": 1,
"name": "张三",
"age": 32,
"address": "北京市",
"salary": 5000.0
},
{
"id": 2,
"name": "李四",
"age": 28,
"address": "上海市",
"salary": 6000.0
}
// ... 其他查询结果
],
"total": 100, // 总记录数
"limit": 10, // 每页显示条数
"offset": 0 // 偏移量
}