参考引用
- SQLite 权威指南(第二版)
- SQLite3 入门
int sqlite3_open(const char *filename, sqlite3 **ppDb);
int sqlite3_exec(sqlite3*,const char *sql,sqlite_callback,void *,char **errmsg);
int sqlite3_close(sqlite3*);
将 sqlite3.h 和 sqlite3.c 拷贝到与 main.c 同级目录下
#include
#include
int main() {
// 1.打开数据库
sqlite3 *ppdb = NULL;
int ret = sqlite3_open("myapi.db", &ppdb);
if (ret != SQLITE_OK) {
perror("open failed");
return -1;
}
// 2.创建一个表格
const char *create_sql = "create table if not exists apitest (id int, name text);";
char *errmsg = NULL; // 存储错误
ret = sqlite3_exec(ppdb, create_sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
printf("%s\n", errmsg);
}
sqlite3_free(errmsg);
// 插入数据
const char *insert_sql = "insert into apitest values(0,'aaa');";
ret = sqlite3_exec(ppdb, insert_sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
printf("%s\n", errmsg);
}
sqlite3_free(errmsg); // 释放内存空间
// 3.关闭数据库
ret = sqlite3_close(ppdb);
return 0;
}
int (*sqlite3_callback)(void*, int, char**, char**);
int LoadMyInfo(void * para, int n_column, char ** column_value, char ** column_name )
#include
#include
// 回调函数是根据查询的数据:有多少行就被调用多少次
// 这个函数调用次数与查询的行数一致,必须返回 0
/* 参数
arg 由 sqlite3_exec() 第四个参数传递过来
int col 查询到的数据的列数
char **values 一行数据有 cols 列
char **names 一行字段名
*/
int callback(void *arg, int cols, char **values, char **names) {
static int flag = 1;
if (flag == 1) {
for (int i = 0; i < cols; i++) {
printf("%s\t", names[i]);
}
printf("\n");
flag = 0;
}
for (int i = 0; i < cols; i++) {
printf("%s\t", values[i]);
}
printf("\n");
return 0;
}
int main() {
// 1.打开数据库
sqlite3 *ppdb = NULL;
int ret = sqlite3_open("myapi.db", &ppdb);
if (ret != SQLITE_OK) {
perror("open failed");
return -1;
}
// 2.创建一个表格
const char *create_sql = "create table if not exists apitest (id int, name text);";
char *errmsg = NULL; // 存储错误
ret = sqlite3_exec(ppdb, create_sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
printf("%s\n", errmsg);
}
sqlite3_free(errmsg);
// 插入数据
const char *insert_sql = "insert into apitest values(0,'aaa');";
ret = sqlite3_exec(ppdb, insert_sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
printf("%s\n", errmsg);
}
sqlite3_free(errmsg);
// 执行查询语句
const char *select_sql = "select * from apitest;";
ret = sqlite3_exec(ppdb, select_sql, callback, NULL, &errmsg);
// 3.关闭数据库
ret = sqlite3_close(ppdb);
return 0;
//return 1; // 只查询一次便返回
}
id name
0 aaa
0 aaa
0 aaa
int sqlite3_get_table(sqlite3*,const char *sql,char ***resultp,int *nrow,int *ncolumn,char **errmsg);
#include
#include
int main() {
// 1.打开数据库
sqlite3 *ppdb = NULL;
int ret = sqlite3_open("myapi.db", &ppdb);
if (ret != SQLITE_OK) {
perror("open failed");
return -1;
}
// 2.创建一个表格
const char *create_sql = "create table if not exists apitest2 (id int, name text);";
char *errmsg = NULL; // 存储错误
ret = sqlite3_exec(ppdb, create_sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
printf("%s\n", errmsg);
}
sqlite3_free(errmsg);
// 插入数据
const char *insert_sql = "insert into apitest2 values(1,'bbb');";
ret = sqlite3_exec(ppdb, insert_sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
printf("%s\n", errmsg);
}
sqlite3_free(errmsg);
// 执行非回调查询
const char *select_sql = "select * from apitest2;";
char **resultp = NULL;
int row = 0;
int col = 0;
ret = sqlite3_get_table(ppdb, select_sql, &resultp, &row, &col, &errmsg);
if (ret != SQLITE_OK) {
printf("%s\n", errmsg);
}
for (int i = 0; i < row + 1; i++) {
for (int j = 0; j < col; j++) {
printf("%s\t", resultp[j +i * col]);
}
printf("\n");
}
// 使用后要释放内存空间
sqlite3_free(errmsg);
sqlite3_free_table(resultp);
// 3.关闭数据库
sqlite3_close(ppdb);
return 0;
}
id name
1 bbb
1 bbb
1 bbb
录入的数据量很大的情况下通常使用数据绑定机制来加快数据插入速度,通常流程如下
// 1、准备
int sqlite3_prepare(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
// 2、绑定数据
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
void(*)(void*));
int sqlite3_bind_double(sqlite3_stmt*, int, double);
int sqlite3_bind_int(sqlite3_stmt*, int, int);
int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
int sqlite3_bind_null(sqlite3_stmt*, int);
int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
void(*)(void*), unsigned char encoding);
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
// 3、执行
int sqlite3_step(sqlite3_stmt*);
// 4、如果循环插入数据(循环绑定)
int sqlite3_reset(sqlite3_stmt *pStmt);
// 5、释放
int sqlite3_finalize(sqlite3_stmt *pStmt);
直接插入数据和绑定插入数据对比
#include
#include
#include
int main() {
// 打开数据库
sqlite3 *ppdb = NULL;
int ret = sqlite3_open("my.db", &ppdb); // 如果存在就直接打开,不存在就创建
//int ret = sqlite3_open(":memory:", &ppdb); // 不会创建文件,直接在内存中操作,关闭后就自动清除(临时数据库)
if (ret != SQLITE_OK) {
perror("open failed");
return -1;
}
// 创建一个表格
const char *create_sql = "create table if not exists test(id int, name text);";
char *errmsg = NULL; // 存储错误
ret = sqlite3_exec(ppdb, create_sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
printf("%s\n", errmsg);
}
sqlite3_free(errmsg);
// 直接插入数据和绑定插入数据对比
// 1、直接插入数据 (分析---编译---执行)
char insert_sql[128]={0};
for(int i = 0; i < 1000; i++) {
sprintf(insert_sql, "insert into test values(%d, %d)", i, i*100);
ret = sqlite3_exec(ppdb, insert_sql, NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
printf("%s", errmsg);
}
}
// 2、绑定插入数据
// 创建 sqlite3_stmt
sqlite3_stmt *stmt = NULL;
// ?表示这两个值是用来绑定的数据
char insert[] = "insert into test values(?,?)"; // 绑定位置顺序从 1 开始
sqlite3_prepare(ppdb, insert, sizeof(insert), &stmt, NULL);
// 绑定数据
for (int i = 0; i < 1000; i++) {
sqlite3_bind_int(stmt, 1, i);
sqlite3_bind_int(stmt, 2, i*200);
// 执行插入
sqlite3_step(stmt);
sqlite3_reset(stmt); // 重置
}
// 释放
sqlite3_finalize(stmt);
sqlite3_close(ppdb); // 关闭数据库
return 0;
}
事务机制可用于提高数据的操作效率
事务回滚
sqlite> select * from device;
0|led|1|0
1|led1|0|0
2|led2|2|0
3|led3|0|0
sqlite> begin; # 开始事务(后面的操作都不在数据库中操作)
sqlite> update device set status=100; # 修改数据
sqlite> select * from device;
0|led|100|0
1|led1|100|0
2|led2|100|0
3|led3|100|0
sqlite> rollback; # 回滚到 begin 前位置
sqlite> select * from device;
0|led|1|0
1|led1|0|0
2|led2|2|0
3|led3|0|0
sqlite>
事务提交
sqlite> begin;
sqlite> select * from device;
0|led|1|0
1|led1|0|0
2|led2|2|0
3|led3|0|0
sqlite> update device set status=123;
sqlite> select * from device;
0|led|123|0
1|led1|123|0
2|led2|123|0
3|led3|123|0
sqlite> commit; # 提交到数据库中,下行的回滚操作将无效
sqlite> rollback;
Error: cannot rollback - no transaction is active
如果没有 begin 开始,直接执行 sql 语句是自动提交事务
用 begin 开始事务,后执行(insert, delete, update)事务需要通过 commit 提交
// 开始事务
ret = sqlite3_exec(ppdb, "begin", NULL, NULL, NULL);
// 执行sql语句 可以通过sqlite3_exec, 绑定机制插入数据
// 提交事务
ret = sqlite3_exec(ppdb, "commit", NULL, NULL, NULL);