文章目录
- SQLite数据库
- 一、SQLite简介
- 1、SQLite和MySQL
- 2、基于嵌入式的数据库
- 二、SQLite数据库安装
- 三、SQLite的常用命令
- 四、SQLite的编程操作
- 1、SQLite数据库相关API
- (1)头文件
- (2)sqlite3_open()
- (3)sqlite3_close()
- (4)sqlite3_errmsg()
- (5)sqlite3_exec()
- (6)sqlite3_prepare_v2()
- (7)sqlite3_step()
- (8)sqlite3_column_*
- (9)sqlite3_mprintf()
- 2、编程实现
- (1)打开数据库
- (2)实现增删改查
- 1.向数据库中增加数据:创建一个表,并且插入三条数据
- 2.更改数据库中的数据:将数据库中num = 1的color改成white
- 3.删除num = 1 的数据
- (3)链表和SQLite数据转换
- 1.静态链表插入SQLite
- 2.动态创建链表插入数据库
- 3.链表方式读取SQLite数据
SQLite数据库
一、SQLite简介
轻量化,易用的嵌入式数据库,用于设备端的数据管理,可以理解成单点的数据库。传统服务器型数据
库用于管理多端设备,更加复杂。
1、SQLite和MySQL
-
SQLite是一个无服务器的数据库,是自包含的。这也称为嵌入式数据库,这意味着数据库引擎作为
应用程序的一部分运行。 -
MySQL需要运行服务器,MySQL将需要客户端和服务器架构通过网络进行交互。
数据库 | 优点 | 缺点 | |
---|---|---|---|
SQLite | 基于文件,易于设置和使用适合基础开发和测试,轻松携带使用标准SQL语法,进行微小修改使用方便 | 缺乏用户管理和安全功能,不容易扩展,不适合大数据库无法定制 | |
MySQL | 使用方便,提供了许多与数据库相关的功能良好的安全功能易于扩展,适用于大型数据库。提供良好的速度和性能提供良好的用户管理和多种访问控制 | 需要一些技术专业知识来设置与传统SQL相比,语法略有不同 |
2、基于嵌入式的数据库
基于嵌入式的数据库主要有:SQLite,Firebird,Berkeley DB,eXtremeDB
- Firebird 是关系型数据库,功能强大,支持存储过程,SQL兼容等
- SQLite 关系型数据库,体积小,支持ACID事务
- Berkeley DB 并没有数据库服务器的概念,他的程序直接链接到应用程序中
- eXtremeDB 是内存数据库,运行效率高
二、SQLite数据库安装
安装方式一:
sudo apt-get -y install sqlite
安装方式二:
https://www.sqlite.org/download.html
把下载的文件sqlite-autoconf-3390000.tar.gz上传到开发板
tar xvf sqlite-autoconf-3390000.tar.gz 解压
cd sqlite-autoconf-3390000 进入文件夹
./configure --prefix=/usr/local 配置安装路径在/usr/local
make 编译//比较久10分钟
sudo make install 安装
如上图,安装成功过,运行sqlite3 进入SQL命令操作流程
三、SQLite的常用命令
1、创建一个数据库
方式一:
sqlite3 //进入数据库
.open test.db //打开(创建)一个名为test的数据库
.quit//退出数据库
数据库退出后在命令当前路径创建数据库test.db
方式二:
sqlite3 test.db //在命令运行当前窗口创建(打开)数据库test.db
.databases //列出当前打开的数据库
.quit //退出
2、创建一张表格
create table stu(id Integer,name char,score Integer);
//创建一个叫stu的表,内容包括id,name,和score
3、插入一条记录
给stu中的值赋值:
insert into stu values(106,'huang',99);
//id = 106,name = huang,score = 99
insert into stu values(101,"gang",100);// ''和""都行
//id = 101,name = gang,score = 100
insert into stu(name,score) values("huanggang",98); //插入部分字段内容
4、查看数据库的记录
.schema stu;//显示指定表的结构(列、数据类型等)。
select * from stu; //查询所有字段的结果
select name,score from stu; //查询数据库中部分字段的内容
5、删除一条记录
delete from stu where id = 101;//删除id = 101的这一项内容
6、更改一条记录
update stu set name = 'huangg' where id = 106;//将id = 106中呢name修改成'huangg'
7、删除一张表
drop table stu;//将名为stu的表删除
8、增加一列
alter table stu add column sex char;//在stu的表中增加一列内容sex
四、SQLite的编程操作
1、SQLite数据库相关API
带有数据库相关API函数编译时要加上 -l sqlite3
(1)头文件
#include <sqlite3.h>
(2)sqlite3_open()
sqlite3_open 函数是 SQLite API 中用于打开或创建 SQLite 数据库的 C 语言函数。
int sqlite3_open( const char *filename,sqlite3 **ppDb);
//返回值:如果成功打开数据库连接,返回 SQLITE_OK(通常为 0)。如果发生错误,返回相应的错误代码。
参数说明:
- filename:指向以 UTF-8 编码的字符串,表示要打开的数据库文件的路径。如果文件不存在,SQLite 将尝试创建它。
- ppDb:一个指向
sqlite3
指针的指针,用于存储新创建的数据库连接句柄。即使发生错误,该参数也会被更新,除非是因为内存分配失败导致无法创建sqlite3
对象。
(3)sqlite3_close()
sqlite3_close函数用于关闭一个打开的 SQLite 数据库连接。
int sqlite3_close(sqlite3 *db);//db:指向 sqlite3 结构的指针,表示要关闭的数据库连接。
//返回值:SQLITE_OK(通常为 0)表示成功关闭连接。错误返回SQLite 错误代码。
(4)sqlite3_errmsg()
sqlite3_errmsg函数用于获取最近一次 SQLite 操作的错误消息。
const char *sqlite3_errmsg(sqlite3 *db);//db:指向 sqlite3的指针,表示已打开的数据库连接。
//返回一个指向错误消息字符串的指针,该字符串描述了调用 SQLite 函数时发生的任何错误。
(5)sqlite3_exec()
sqlite3_exec是 SQLite 库中的一个便捷函数,它封装了多个任务,用于执行 SQL 语句并可通过回调函数接口收集返回数据。
int sqlite3_exec(sqlite3 *db, // 数据库连接句柄const char *sql, // 要执行的 SQL 语句int (*callback)(void*, int, char **, char **), // 回调函数void *, // 给回调函数传的参数char **errmsg // 错误信息
);
//返回值:SQLITE_OK(通常为 0)表示执行成功。其他值表示发生错误。
参数说明:
- db:指向
sqlite3
结构的指针,表示已打开的数据库连接。 - sql:指向包含要执行的 SQL 语句的零结尾字符串的指针。
- callback:每成功执行一次 SQL 语句,就执行一次此回调函数。如果 SQL 语句不是一个查询(例如
INSERT
、UPDATE
或DELETE
),则此参数可以设置为NULL
。 - **void ***:这是传递给回调函数的用户定义参数,对应于
sqlite3_exec
函数的第四个参数。 - errmsg:如果提供了这个参数,并且函数返回了错误(非
SQLITE_OK
),则错误信息将被存储在这个参数指向的位置。调用者应该在处理完错误消息后使用sqlite3_free
释放这个指针。
其中回调函数callback要注意的是:
回调函数应该返回一个整数,一般是return 0。通常,返回 SQLITE_OK(值为 0)表示继续处理下一行。如果返回非零值,sqlite3_exec 将停止执行 SQL 语句并返回。 |
typedef int (*sqlite3_callback)(void *arg, // 用户定义的数据指针int column_size, // 列的数量char *column_value[], // 列值的数组char *column_name[] // 列名的数组
);
参数说明:
- arg:这是一个用户定义的数据指针,它被传递给
sqlite3_exec
函数,并且最终传递给回调函数。这可以用来在回调函数内部访问额外的数据或状态。 - column_size:表示查询结果中的列数。
- *column_value[]:这是一个指向字符指针数组的指针,每个元素包含一行中每个列的文本表示形式。可以通过
column_value[i]
来访问第i
列的名称,索引从 0 开始。 - *column_name[]:这是一个指向列名的指针数组。每个元素对应一列的名称,可以通过
column_name[i]
来访问第i
列的名称。
(6)sqlite3_prepare_v2()
sqlite3_prepare_v2函数用于编译 SQL 语句,并生成一个准备语句(prepared statement),这个准备语句可以被进一步用于参数绑定和执行。相比于 sqlite3_exec
,使用 sqlite3_prepare_v2
可以提高执行效率,因为 SQL 语句只需要编译一次,可以被重复执行多次。
int sqlite3_prepare_v2(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 */
);
//返回值:成功返回 SQLITE_OK,失败返回相应的错误码。
参数说明:
- db :指向 SQLite 数据库连接的指针。
- zSql: 指向要编译的 SQL 语句的指针,该语句是 UTF-8 编码。
- nByte: 是SQL 语句的最大字节长度。如果设置为负数,则 SQLite 会自己确定字符串的长度。
- ppStmt: 是指向
sqlite3_stmt
指针的指针,用于接收编译后的 SQL 语句的句柄。- 它不是普通的 SQL 语句字符串,而是一个已经编译成二进制形式的实例,可以直接执行。
- 通过调用
sqlite3_step
函数,可以执行sqlite3_stmt
对象中的 SQL 语句。这个函数可以被调用一次或多次,用于循环执行。 - 执行完所有操作后,使用
sqlite3_finalize
函数销毁sqlite3_stmt
对象,释放与之关联的所有资源。
- pzTail: 是指向剩余未编译 SQL 语句部分的指针的指针,如果 SQL 语句被成功编译,这个参数会被设置为指向
zSql
之后的第一个字符。
(7)sqlite3_step()
sqlite3_step是SQLite中用于执行或继续执行由 sqlite3_stmt
表示的准备语句的函数。这个函数通常在调用 sqlite3_prepare_v2
或 sqlite3_prepare
准备 SQL 语句后使用。
int sqlite3_step(sqlite3_stmt *stmt);
执行流程:
- 第一次调用:当
sqlite3_step
被首次调用时,它会开始执行 SQL 语句。 - 后续调用:如果 SQL 语句是一个查询,并且有多行结果,
sqlite3_step
会在后续调用中返回下一行结果。
使用场景:
- 查询:当执行一条 SELECT 语句时,
sqlite3_step
用于逐行获取查询结果。 - 插入、更新、删除:对于这类操作,
sqlite3_step
通常只被调用一次,完成操作后返回SQLITE_DONE
。
返回值:sqlite3_step
函数返回一个状态码,表示执行的状态
SQLITE_DONE
:表示语句已经成功执行完成,没有更多的结果行。SQLITE_ROW
:表示 SQL 语句是一条查询,且sqlite3_step
返回了一行结果。此时,可以使用sqlite3_column_*
系列函数访问结果列的数据。SQLITE_BUSY
:表示数据库忙,通常是因为另一个操作正在使用数据库。SQLITE_ERROR
:表示执行过程中发生了错误。可以使用sqlite3_errmsg
或sqlite3_errcode
函数获取错误详情。- 其他错误码:SQLite 定义了其他错误码,表示特定的错误情况。
(8)sqlite3_column_*
**sqlite3_column_***是一组 SQLite API 函数,用于从 sqlite3_stmt
对象中检索单个列的数据,该对象是通过执行 SQL 查询语句得到的。
TYPE sqlite3_column_COLUMNNAME(sqlite3_stmt *stmt, int iCol);
函数说明:
- TYPE: 是数据类型,例如
int
、double
、text
等。 - COLUMNNAME: 是列的类型或特定属性的名称,例如
int
、real
、blob
等。 - stmt: 是指向
sqlite3_stmt
对象的指针,该对象包含了查询结果。 - iCol: 是列的索引号(从 0 开始)。
常用函数
sqlite3_column_blob
:返回列的 BLOB 数据。sqlite3_column_double
:返回列的 REAL 数据。sqlite3_column_int
:返回列的 INTEGER 数据。sqlite3_column_int64
:返回列的 64位 INTEGER 数据。sqlite3_column_text
:返回列的 TEXT 数据的指针。sqlite3_column_value
:返回列的sqlite3_value
对象。
这些函数用于访问由 sqlite3_step
返回的当前行的数据。每调用一次 sqlite3_step
并返回 SQLITE_ROW
后,就可以使用 sqlite3_column_*
函数来访问当前行的列数据。
(9)sqlite3_mprintf()
sqlite3_mprintf函数用于格式化字符串,类似于标准 C 语言中的 printf
函数,但它使用 SQLite 的内存分配函数来分配生成的字符串。这个函数在 SQLite 的 API 中非常有用,特别是在需要构造 SQL 语句时。
char *sqlite3_mprintf(const char *format, ...);
//返回值:函数返回一个指向新分配的字符串的指针,该字符串是格式化后的输出。如果分配内存失败,返回 NULL。
参数说明:
- format:这是格式字符串,它指定了如何格式化后续参数。它遵循与
printf
函数相同的格式说明符。
使用示例:
char *sql;
int id = 10;
const char *name = "example";
sql = sqlite3_mprintf("SELECT * FROM table WHERE id=%d AND name='%q'", id, name);
- 由于
sqlite3_mprintf
分配了内存,调用者有责任在不再需要时使用sqlite3_free
来释放它。 - 格式化选项
%q
是特殊的,在 SQLite 中用于确保字符串被正确地引用,避免 SQL 注入攻击。不过,需要注意的是,%q
并不是所有编译器都支持的。
2、编程实现
(1)打开数据库
#include <stdio.h>
#include <sqlite3.h> int main(int argc, char *argv[]) // 主函数入口,argc 是参数个数,argv 是参数数组
{int ret; // 用于存储 SQLite 函数的返回值sqlite3 *db; // 用于存储数据库连接的指针// 检查命令行参数的数量是否正确(应提供一个数据库文件名)if(argc != 2){printf("Usage:%s xxx.db\n",argv[1]); // 如果参数数量不正确,打印用法信息return -1; }// 尝试打开数据库文件,argv[1] 是命令行提供的数据库文件名// sqlite3_open 函数尝试打开或创建一个数据库,并将数据库连接的指针存储在 db 指向的位置if((ret = sqlite3_open(argv[1],&db)) != SQLITE_OK){printf("error:%s,%d\n",sqlite3_errmsg(db),ret); //如果打开失败,打印错误信息和错误代码return -1;}else{printf("open %s success\n",argv[1]); //如果打开成功,打印成功信息}// 关闭数据库连接sqlite3_close(db); printf("done\n"); // 打印完成信息return 0;
}
运行结果:成功打开数据库test3.db
(2)实现增删改查
1.向数据库中增加数据:创建一个表,并且插入三条数据
#include <stdio.h>
#include <sqlite3.h> // 回调函数原型,由 sqlite3_exec 调用以处理查询结果
int callback(void *arg, int column_size, char *column_value[], char *column_name[])
{int i;printf("column_size = %d\n", column_size); // 打印结果集中的列数printf("arg = %s\n", (char *)arg); // 打印传递给回调函数的参数,这里通常是 NULLfor(i = 0; i < column_size; i++) {// 打印每一列的名称和值,如果值为 NULL,则打印 "NULL"printf("%s = %s\n", column_name[i], column_value[i] ? column_value[i] : "NULL");}printf("==================\n");return 0; // 回调函数返回 0 以继续执行
}int main(int argc, char *argv[])
{int ret; // 用于存储 SQLite 函数的返回状态char *errorMes = NULL; // 用于存储错误消息/* 定义 SQL 语句字符串*///创建一个名为Colors的表char *Sql_cretable = "create table Colors(num Integer, color char);";//Colors表中插入数据char *Sql_insert = "insert into Colors values(1,'black'),""(2,'pink'),""(3,'purple');";//查询Colors表中的所有数据char *Sql_select = "select * from Colors;";sqlite3 *db; // SQLite 数据库连接的指针// 检查命令行参数数量是否正确if(argc != 2){printf("Usage:%s xxx.db\n", argv[1]);return -1; // 参数数量不正确时,打印用法并退出}// 尝试打开数据库,如果失败打印错误消息并退出if((ret = sqlite3_open(argv[1], &db)) != SQLITE_OK){printf("error:%s\n", sqlite3_errmsg(db));return -1;}printf("open %s success\n", argv[1]); // 打开成功,打印消息// 执行创建表的 SQL 语句,如果失败打印错误if((ret = sqlite3_exec(db, Sql_cretable, NULL, NULL, &errorMes)) != SQLITE_OK){printf("error:%s\n", errorMes);}printf("create Colors success\n"); // 创建表成功,打印消息// 执行插入数据的 SQL 语句,如果失败打印错误if((ret = sqlite3_exec(db, Sql_insert, NULL, NULL, &errorMes)) != SQLITE_OK){printf("error:%s\n", errorMes);}printf("insert success\n"); // 插入数据成功,打印消息// 执行查询数据的 SQL 语句,并使用回调函数处理结果if((ret = sqlite3_exec(db, Sql_select, callback, NULL, &errorMes)) != SQLITE_OK){printf("error:%s\n", errorMes);}printf("select success\n"); // 查询成功,打印消息sqlite3_close(db);// 关闭数据库连接printf("done\n"); return 0;
}
运行结果:
2.更改数据库中的数据:将数据库中num = 1的color改成white
#include <stdio.h>
#include <sqlite3.h> //回调函数,由 sqlite3_exec 调用以处理查询结果
int callback(void *arg, int column_size, char *column_value[], char *column_name[])
{int i;printf("column_size = %d\n", column_size); // 打印结果集中的列数printf("arg = %s\n", (char *)arg); // 打印传递给回调函数的参数,这里通常是 NULLfor(i = 0; i < column_size; i++) {// 打印每一列的名称和值,如果值为 NULL,则打印 "NULL"printf("%s = %s\n", column_name[i], column_value[i] ? column_value[i] : "NULL");}printf("==================\n");return 0; // 回调函数返回 0 以继续执行
}int main(int argc, char *argv[])
{int ret; // 用于存储 SQLite 函数的返回状态char *errorMes = NULL; // 用于存储错误消息/*定义 SQL 语句字符串*///更新表中num = 1的数据char *Sql_update = "update Colors set color = 'white' where num = 1;";// 查询 Colors 表中的所有数据char *Sql_select = "select * from Colors;"; sqlite3 *db; // SQLite 数据库连接的指针// 检查命令行参数数量是否正确if(argc != 2){printf("Usage:%s xxx.db\n", argv[1]);return -1; // 参数数量不正确时,打印用法并退出}// 尝试打开数据库,如果失败打印错误消息并退出if((ret = sqlite3_open(argv[1], &db)) != SQLITE_OK){printf("error:%s\n", sqlite3_errmsg(db));return -1;}printf("open %s success\n", argv[1]); // 打开成功,打印消息// 执行更新数据的 SQL 语句,并使用回调函数处理结果if((ret = sqlite3_exec(db, Sql_update, callback, NULL, &errorMes)) != SQLITE_OK){printf("error:%s\n", errorMes);}printf("update success\n"); // 更新成功,打印消息// 关闭数据库连接sqlite3_close(db);printf("done\n");return 0;
}
运行结果:
3.删除num = 1 的数据
#include <stdio.h>
#include <sqlite3.h> // 回调函数原型,由 sqlite3_exec 调用以处理查询结果
int callback(void *arg, int column_size, char *column_value[], char *column_name[])
{int i;printf("column_size = %d\n", column_size); // 打印结果集中的列数printf("arg = %s\n", (char *)arg); // 打印传递给回调函数的参数,这里通常是 NULLfor(i = 0; i < column_size; i++) {// 打印每一列的名称和值,如果值为 NULL,则打印 "NULL"printf("%s = %s\n", column_name[i], column_value[i] ? column_value[i] : "NULL");}printf("==================\n");return 0; // 回调函数返回 0 以继续执行
}int main(int argc, char *argv[])
{int ret; // 用于存储 SQLite 函数的返回状态char *errorMes = NULL; // 用于存储错误消息/* 定义 SQL 语句字符串*/// 删除 Colors 表中num = 1的数据char *Sql_delete = "delete from Colors where num = 1;";// 查询 Colors 表中的所有数据char *Sql_select = "select * from Colors;";sqlite3 *db; // SQLite 数据库连接的指针// 检查命令行参数数量是否正确if(argc != 2){printf("Usage:%s xxx.db\n", argv[1]);return -1; // 参数数量不正确时,打印用法并退出}// 尝试打开数据库,如果失败打印错误消息并退出if((ret = sqlite3_open(argv[1], &db)) != SQLITE_OK){printf("error:%s\n", sqlite3_errmsg(db));return -1;}printf("open %s success\n", argv[1]); // 打开成功,打印消息// 执行删除数据的 SQL 语句,如果失败打印错误if((ret = sqlite3_exec(db, Sql_delete, NULL, NULL, &errorMes)) != SQLITE_OK){printf("error:%s\n", errorMes);}printf("delete success\n"); // 删除成功,打印消息// 再次执行查询数据的 SQL 语句,验证删除操作的结果if((ret = sqlite3_exec(db, Sql_select, NULL, NULL, &errorMes)) != SQLITE_OK){printf("error:%s\n", errorMes);}printf("select success\n"); // 查询成功,打印消息// 关闭数据库连接sqlite3_close(db);printf("done\n"); return 0;
}
运行结果:
(3)链表和SQLite数据转换
1.静态链表插入SQLite
#include <stdio.h> // 包含标准输入输出库
#include <sqlite3.h> // 包含 SQLite 库的头文件struct Stu {int id; // 学生IDint class; // 班级char name[12]; // 学生姓名int scores; // 分数struct Stu *next; // 指向下一个链表节点的指针
};// 回调函数原型,由 sqlite3_exec 调用以处理查询结果
int callback(void *arg, int column_size, char *column_value[], char *column_name[])
{int i;printf("column_size = %d\n",column_size);printf("arg = %s\n",(char *)arg);for(i=0; i<column_size;i++){printf("%s = %s\n",column_name[i],column_value[i]);}printf("==================\n");return 0;
}int main(int argc, char *argv[]) {int ret; // 函数返回状态char *errorMes = NULL; // 错误信息// 定义 SQL 语句char *Sql_cretable = "create table Stu(id Integer,class Integer,name\ char,scores Integer);";char *Sql_select = "select * from Stu;";char *sql = NULL; // 动态 SQL 语句字符串 sqlite3 *db; // SQLite 数据库连接指针// 定义链表节点struct Stu stu1 = {1, 1801, "dafang", 99, NULL};struct Stu stu2 = {2, 1801, "xiaohong", 68, NULL};struct Stu stu3 = {3, 1801, "zhangsan", 88, NULL};// 初始化链表头指针并构建链表struct Stu *head = &stu1;head->next = &stu2;stu2.next = &stu3;// 检查命令行参数数量if (argc != 2) {printf("Usage:%s xxx.db\n", argv[1]);return -1;}// 打开 SQLite 数据库if ((ret = sqlite3_open(argv[1], &db)) != SQLITE_OK) {printf("error:%s,%d\n", sqlite3_errmsg(db), ret);return -1;} else {printf("open %s success\n", argv[1]);}// 创建表if ((ret = sqlite3_exec(db, Sql_cretable, NULL, NULL, &errorMes)) !=\ SQLITE_OK) {printf("error:%s\n", errorMes);}printf("create Stu table success\n");// 遍历链表并插入数据while (head != NULL) {// 构建 SQL 插入语句sql = sqlite3_mprintf("insert into Stu(id,class,name,scores)\ values(%d,%d,%Q,%d)",\head->id, head->class, head->name, head->scores);// 执行 SQL 插入语句if ((ret = sqlite3_exec(db, sql, NULL, NULL, &errorMes)) != SQLITE_OK) {printf("error:%s\n", errorMes);}// 释放动态分配的 SQL 语句内存sqlite3_free(sql);// 移动到链表的下一个节点head = head->next;}printf("insert success\n");// 执行查询并打印结果if ((ret = sqlite3_exec(db, Sql_select, callback, NULL, &errorMes)) != SQLITE_OK) {printf("error:%s\n", errorMes);}printf("select success\n");sqlite3_close(db); // 关闭数据库连接printf("done\n");return 0;
}
运行结果:
2.动态创建链表插入数据库
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h> // 定义学生结构体
struct Stu {int id; // 学生IDint class; // 班级编号char name[12]; // 学生姓名,假设最大长度为12int scores; // 分数struct Stu *next; // 指向下一个学生结构的指针,用于构建链表
};// 回调函数,用于 sqlite3_exec 函数查询操作
int callback(void *arg, int column_size, char *column_value[], char *column_name[])
{int i;printf("column_size = %d\n",column_size);printf("arg = %s\n",(char *)arg);for(i=0; i<column_size;i++){printf("%s = %s\n",column_name[i],column_value[i]);}printf("==================\n");return 0;
}/*提示用户输入学生信息,然后将这些信息插入到数据库中。使用 sqlite3_mprintf 来安全地格式化 SQL 插入命令,并使用 sqlite3_exec 来执行这些命令。*/
// 创建数据并插入到数据库的函数
int createData(sqlite3 *db)
{int ret; // 用于存储 sqlite3_exec 函数的返回值char *sql; // 用于存储构建的 SQL 语句char *errorMes = NULL; // 用于存储可能发生的错误信息struct Stu *new; // 指向新分配的 Stu 结构的指针;// 提示用户输入数据printf("Please input data:id Integer,class Integer,name char,scores Integer\n");printf("input 0 0 0 0 quit!\n");while(1){new = (struct Stu *)malloc(sizeof(struct Stu)); scanf("%d%d%s%d",&new->id,&new->class,new->name,&new->scores);new->next = NULL;printf("id=%d,class=%d,name=%s,scores=%d\n",\new->id,new->class,new->name,new->scores);if((new->id == 0) && (new->class == 0) && (new->scores == 0)){return 0;}sql = sqlite3_mprintf("insert into Stu(id,class,name,scores) \values(%d,%d,%Q,%d)",\new->id,new->class,new->name,new->scores);if((ret = sqlite3_exec(db,sql,NULL,NULL,&errorMes)) != SQLITE_OK){printf("error: %s\n",errorMes);}sqlite3_free(sql);}return 0;
}int main(int argc, char *argv[]) {// 检查命令行参数数量if (argc != 2) {printf("Usage: %s database_name.db\n", argv[0]);return -1;}// 打开 SQLite 数据库sqlite3 *db;if (sqlite3_open(argv[1], &db) != SQLITE_OK) {// 打印错误信息并退出printf("Cannot open database: %s\n", sqlite3_errmsg(db));return -1;}printf("Opened database successfully\n");// 创建学生表的 SQL 语句char *Sql_cretable = "CREATE TABLE IF NOT EXISTS Stu (id INTEGER, class INTEGER, name TEXT, scores INTEGER);";// 执行创建表的 SQL 语句char *errorMes;if (sqlite3_exec(db, Sql_cretable, NULL, NULL, &errorMes) != SQLITE_OK) {printf("Error creating table: %s\n", errorMes);}printf("Table created successfully\n");// 调用函数创建数据并插入数据库int ret = createData(db);// 执行查询并打印结果char *Sql_select = "SELECT * FROM Stu;";if (sqlite3_exec(db, Sql_select, callback, NULL, &errorMes) != SQLITE_OK) {printf("Error querying the database: %s\n", errorMes);}printf("Query executed successfully\n");// 关闭数据库连接sqlite3_close(db);printf("Database closed\n");return 0;
}
运行结果:
3.链表方式读取SQLite数据
#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h> struct Stu { // 定义学生结构体int id; // 学生IDint class; // 班级char name[12]; // 学生姓名int scores; // 分数struct Stu *next; // 指向下一个学生节点的指针
};// 回调函数,用于sqlite3_exec查询数据库内容
int callback(void *arg, int column_size, char *column_value[], char *column_name[]) {// ... 此处实现回调函数,用于打印查询结果 ...
}// 定义从数据库创建链表的函数
struct Stu *createListFromDB(sqlite3 *db) {sqlite3_stmt *stmt; // 存储编译后的SQL语句struct Stu *head = NULL; // 链表头初始化为NULLstruct Stu *node = NULL; // 链表的节点指针struct Stu *current = NULL; // 遍历链表的当前节点char *Sql_select = "select * from Stu;"; // 查询SQL语句// 准备SQL查询语句sqlite3_prepare_v2(db, Sql_select, -1, &stmt, NULL);while (sqlite3_step(stmt) == SQLITE_ROW) { // 遍历查询结果node = (struct Stu *)malloc(sizeof(struct Stu)); // 为新节点分配内存if (node == NULL) { // 检查内存分配是否成功fprintf(stderr, "malloc failed\n");break;}// 从数据库查询结果中获取数据并赋值给节点成员node->id = sqlite3_column_int(stmt, 0);node->class = sqlite3_column_int(stmt, 1);snprintf(node->name, sizeof(node->name), "%s", \(char *)sqlite3_column_text(stmt, 2));node->scores = sqlite3_column_int(stmt, 3);// 将新节点添加到链表if (head == NULL) {head = node; // 如果链表为空,则新节点是头节点} else {current->next = node; // 否则,将新节点链接到链表末尾}current = node; // 更新当前节点为新节点}sqlite3_finalize(stmt); // 最终化SQL语句return head; // 返回链表的头指针
}// 释放链表内存的函数
void freeList(struct Stu *head) {struct Stu *tmp;while (head != NULL) {tmp = head; // 暂存当前节点head = head->next; // 移动到下一个节点free(tmp); // 释放当前节点的内存}
}int main(int argc, char *argv[]) {int ret; // 用于存储函数返回值sqlite3 *db; // 用于存储数据库连接的指针// 检查命令行参数数量if (argc != 2) {printf("Usage:%s xxx.db\n", argv[1]);return -1;}// 打开SQLite数据库if ((ret = sqlite3_open(argv[1], &db)) != SQLITE_OK) {printf("error:%s,%d\n", sqlite3_errmsg(db), ret);return -1;} else {printf("open %s success\n", argv[1]);}// 使用createListFromDB函数从数据库创建链表struct Stu *stuList = createListFromDB(db);if (stuList != NULL) {// 遍历链表并打印学生信息struct Stu *ptr = stuList;while (ptr) {printf("ID: %d, Class: %d, Name: %s, Score: %d\n",\ptr->id, ptr->class, ptr->name, ptr->scores);ptr = ptr->next;}// 释放链表占用的内存freeList(stuList);}// 关闭数据库连接sqlite3_close(db);printf("done\n");return 0;
}
运行结果: