目录
1.Demo1.c(执行select * from student.db)
2.Demo2.c(在demo1的基础上,将数据存在链表中)
本篇浅学嵌入式数据库SQLite,关于SQLite的详细教程可参考:SQLite教程丨菜鸟教程
一、SQLite数据库简介
SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的SQL 数据库引擎,也称嵌入式数据库。它是一个零配置的数据库,这意味着与其他数据库不一样,不需要在系统中配置。就像其他数据库,SQLite 引擎不是一个独立的进程,作为应用程序一部分运行,可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件。
(MySQL需要运行服务器,需要服务器和客户端通过网络交互)
SQLite | MySQL | |
优点 |
|
|
缺点 |
|
|
此外,基于嵌入式的数据库还有:Firebird、Berkeley DB、eXtreme DB
🔖SQLite是关系型数据库,体积小支持ACID事务
🔖Firebird是关系型数据库,支持存储过程,SQL兼容
🔖Berkeley DB没有数据库服务器概念,程序直接链接到应用程序
🔖eXtreme DB内存数据库,运行速度快
二、安装SQLite3数据库(ubuntu20.04下)
方式一:直接下载安装
(可能会出现安装不了SQLite3,可以改用第二种安装)
root@ubuntu:~# sudo apt-get install sqlite3
方式二:源码包编译安装
这里下载的是最新版sqlite-autoconf-3390100.tar.gz
(从官网下载好SQLite3的压缩包后,解压后开始进行编译和安装)
Step1:解压源码包 tar -zxvf sqlite-autoconf-3390100.tar.gz
Step2:进入源码包主目录 cd sqlite-autoconf-3390100/
Step3:配置安装路径 ./configure --prefix=/usr/local
Step4:编译 make
Step5:安装 make install大部分第三方源码包的安装方法
三、SQLite基础操作(Linux)
1.SQLite下的点命令
(SQLite下嵌入了简单实用的命令,不同于SQL语句,这些命令不以;结尾。提供了查看、创建数据库等操作的功能,如.open student.db打开student数据库。这样的命令也称为点命令)
🔖打开/创建数据库.open
.open+databasename.db 打开数据库,不存在就创建
.database 查看所有数据库信息
sqlite> .open student.db
sqlite> .database
main: /root/student.db r/w
sqlite>
🔖查看数据库中所有表.table
sqlite> .table
stu_Info teacher_info
sqlite>
🔖输出模式.mode
.mode column 显示表头字段
sqlite> .mode column
sqlite> select * from stu_Info;
ID name age register
-- -------- --- --------
1 zhangsan 18
2 lisi 19 1
🔖帮助信息.help
sqlite> .help
.archive ... Manage SQL archives
.auth ON|OFF Show authorizer callbacks
.echo on|off Turn command echo on or off
sqlite>
(这里只截取了几条 .help会列出所有点命令的使用帮助)
2.SQL基本语句操作表
🔖创建表、删除表
例:创建学生信息表,包含字段有学号ID、姓名name、年龄age、注册信息register
sqlite> create table stu_Info (ID int,name char,age int,register bool);
sqlite>
🔖向表中增加数据(增)
例1:向表中写入学生王五(3,19,已注册)的数据
sqlite> insert into stu_Info values(3,"wangwu",19,1);
sqlite> select * from stu_Info;
ID name age register
-- -------- --- --------
1 zhangsan 18
2 lisi 19 1
3 wangwu 19 1
sqlite>
例2:向表中写入学生小明(已知小明的学号4)的数据
sqlite> insert into stu_Info(ID,name)
values(4,"xiaoming");
sqlite> select * from stu_Info;
ID name age register
-- -------- --- --------
1 zhangsan 18
2 lisi 19 1
3 wangwu 19 1
4 xiaoming
sqlite>
🔖删除表中的数据(删)
例:删除学生信息表中没有注册的学生信息
sqlite> delete from stu_Info where register is NULL
sqlite> select * from stu_Info;
ID name age register
-- ------ --- --------
2 lisi 19 1
3 wangwu 19 1
sqlite>
🔖修改表中的数据(改)
例:将wangwu的年龄修改为20岁
sqlite> update stu_Info set age=20 where name="wangwu";
sqlite> select * from stu_Info;
ID name age register
-- ------ --- --------
2 lisi 19 1
3 wangwu 20 1
sqlite>
🔖查询表中的数据(查)
例1:查询表中所有学生数据
sqlite> .mode column
sqlite> select * from stu_Info;
ID name age register
-- -------- --- --------
1 zhangsan 18
2 lisi 19 1
例2:查询表中所有学生的姓名和年龄
sqlite> select name,age from stu_Info;
name age
-------- ---
zhangsan 18
lisi 19
sqlite>
例3:查询未注册的学生信息
sqlite> select * from stu_Info where register is NULL;
ID name age register
-- -------- --- --------
1 zhangsan 18
sqlite>
四、SQLite的C编程
在C/C++程序中使用SQLite之前,需要确保机器上已经有SQLite库。在编译程序时需要加选项-lsqlite3链接到SQLite的库。
1.打开数据库sqlite3_open
✒️函数原型int sqlite3_open(const char *zFilename,sqlite3 **ppDb); ✒️参数说明:①zFilename:打开的数据库名(如:student.db),不为NULL将以附加的方式打开该数据库,如果为NULL,会在RAM中创建一个只在当前会话有效的临时内存数据库。 ②ppDb:指向操作数据库的句柄的地址 ✒️返回值:0-28和100-101表示执行状态的整数(以下是对应的宏定义) |
2.关闭数据库sqlite3_close
✒️函数原型:int sqlite3_close(sqlite3 *db); ✒️参数说明:db 关闭数据库的操作句柄 ✒️返回值:同上0-28和100-101表示执行状态的整数 |
3.执行SQL语句sqlite3_exec
✒️函数原型: SQLITE_API int sqlite3_exec( sqlite3 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ sqlite3_callback xCallback, /*Invoke this callback routine*/ void *pArg, /* First argument to xCallback() */ char **pzErrMsg /* Write error messages here */ ) ✒️参数说明:参考注释(摘自sqlite3源码) 参数1 /* 执行SQL语句所在的数据库 */ 参数2 /* 执行的SQL语句 */ 参数3 /* 调用执行的回调函数程序 */ 参数4 /* 回调函数的第一个参数 */ 参数5 /* 记录错误信息 */ ✒️返回值:同上 |
4.(重要)回调函数callback
✒️函数原型 static int callback(void *pArg,int nArg,char **azArg,char **azCol); (上面是从sqlite3源码中截下来callback的函数原型,个人感觉参数名不大清晰) static int callback(void *arg,int col_size,char **col_val,char **col_name); ✒️参数说明 /* 参数1-void *pArg 由sqlite_exec函数传过来的参数(具体意义没有查到?) 参数2-int nArg 回传过来的字段数(表的列数) 参数3-char **azArg 存放表的数据的地址(字段的值) 参数4-char **azCol 存放表的行(字段名)*/ ✒️返回值 /* 返回值为0时表中有几条数据就执行几次 */ |
五、C操作SQLite数据库
1.Demo1.c(执行select * from student.db)
#include <stdio.h>
#include <sqlite3.h>
/* int callback(void *pArg, int nArg, char **azArg, char **azCol)*/
/* 回调函数,返回值为0时表中有几条数据就执行几次 */
/* 参数1-void *pArg 由sqlite_exec函数传过来的参数
参数2-int nArg 回传过来的字段数(表的列数)
参数3-char **azArg 存放表的数据(字段的值)
参数4-char **azCol 存放表的行(字段名)
*/
int callback(void *pArg, int nArg, char **azArg, char **azCol){
static int i = 0;
if(!i){
printf("%s\n",(char *)pArg); //表的标题,由sqlite3_exec传过来的
for(i=0;i<nArg;i++){
printf("%s\t",azCol[i]); //只打印输出一次表的字段名(表头)
}
printf("\n");
printf("----------------------------------\n");
}
for(i=0;i<nArg;i++){
printf("%s\t",azArg[i]); //打印输出表的数据
}
printf("\n");
return 0;
}
int main(int argc,char **argv){
sqlite3 *pdb;
char SQL_SELECT[] = "select * from stu_Info;";
char *errorLog = NULL;
void *p;
if(argc < 2){
printf("Usage:%s XXX.db\n",argv[0]);
return -1;
}else{
if(sqlite3_open(argv[1],&pdb) == SQLITE_OK){ //打开数据库
printf("open %s succeed!\n",argv[1]);
if(sqlite3_exec(pdb,SQL_SELECT,callback,"student messege table",&errorLog)!=SQLITE_OK){ //执行SQL语句
printf("SQL execute error %s\n",errorLog); //执行失败打印错误信息
}
}else{
printf("open error:%d\n",sqlite3_errcode(pdb)); //打开数据库失败输出错误码
}
}
sqlite3_close(pdb);
return 0;
}
2.Demo2.c(在demo1的基础上,将数据存在链表中)
(不会,mark以后再看看)
3.Demo3.c(创建表,并插入数据)
#include <stdio.h>
#include <sqlite3.h>
int callback(void *arg,int col_size,char **col_val,char **col_name){
static int i = 0;
if(!i){
for(i=0;i<col_size;i++){
printf("%s\t",col_name[i]); //只打印输出一次表的字段名(表头)
}
printf("\n");
printf("----------------------------------\n");
}
for(i=0;i<col_size;i++){
printf("%s\t",col_val[i]); //打印输出表的数据
}
printf("\n");
return 0;
}
int main(int argc,char **argv){
sqlite3 *pdb;
int retn;
char *errorLog;
/* 创建成绩表,字段如下。为了美观代码分行,需加\连接*/
char Create_Table[] = "create table scores( \
ID char primary key,\
name char not null, \
class int not null, \
score int \
);";
char Select_Table[] = "select * from scores;";
char Insert_Table1[] = "insert into scores values('2022001','Socket',001,99);";
char Insert_Table2[] = "insert into scores values('2022002','AF_INET',001,88);";
char Insert_Table3[] = "insert into scores values('2022003','New',002,77);";
if(argc < 2){
printf("syntax error\nUages:%s xxx.db\n",argv[0]);
return -1;
}
retn = sqlite3_open(argv[1],&pdb);
if(retn != SQLITE_OK){
printf("open %s error:%d\n",argv[1],sqlite3_errcode(pdb));
return -1;
}else{
printf("open %s succeed\n",argv[1]);
}
retn = sqlite3_exec(pdb,Create_Table,NULL,NULL,&errorLog);
if(retn != SQLITE_OK){
printf("%s,error code:%d\n",errorLog,retn);
}
retn = sqlite3_exec(pdb,Insert_Table3,NULL,NULL,&errorLog);
if(retn == SQLITE_OK){
printf("Insert data succeed\n");
}else{
printf("%s,error code:%d\n",errorLog,retn);
}
sqlite3_exec(pdb,Select_Table,callback,NULL,&errorLog);
sqlite3_close(pdb);
return 0;
}