在物联网的小项目中我们经常使用到数据库,无论是物联网服务器上的存储还是硬件设备的本地存储。因此本章鑫哥带小伙伴们来搞一搞我们嵌入式+物联网中典型的一个数据库-sqlite3
sqlite3数据库
1.sqlite3的特殊指令(都是以.开头的)
1.1打开数据库
sqlite3 xx.db
使用sqlite3管理系统打开文件名叫做xx的数据库文件
.db表示数据库文件后缀
1.2退出数据库
.quit或者.exit
1.3查询信息
.database
1.4查询显示数据库中所有的表
.tables 或者 .table
1.5查询显示创建表的结构
.schema xxx xx表示表名称,这个时候就是
查看显示xxx表的结构,如果不写xxx这个时候查的是所有表
表的结构就是你创建表的那句话
2.sql语句(sql中的语言)
增删改查:
新建修改删除表
插入修改删除行
查询
2.1新建一张数据表
语法:
create table 表的名称 (列名称 列数据类型, 列名称 数据类型);
例如:
create table persons (id int, name text);
创建一张表 表名为persons 表中两列 分别为id(int类型的)、name(文本类型的)
创建成功就是没有反应的
3.修改表的结构
语法:alter table 表名 rename to 新表名; (修改表的名称)
alter table 表名 add 列名 数据类型;(修改表的结构,添加新的一列)
在sqlite3中没有直接删除一列的sql语句,我们可以先新建一个表,将原表中除了你想删除的那列以外的所有列复制粘贴到新表中,删除旧表,将新表名设置为老表名。
4.删除表
语法: drop table 表名 ;
5.插入新的一行数据
语法:
insert into 表名 values (列值1,列值2.....); 全部赋值
insert into 表名 (列名称,列名称) values ( 对应的列值);部分赋值
例如:(切记插入的过程中列值为字符串需要用" ")
6.修改行中数据
语法:
update 表名 set 列名称 = 列值 匹配条件;
例如: 修改haha表中name那一列设置为文静,当你的id为10的那一行
7.删除表中一行数据或者匹配到的多行数据
语法:
delete from 表名 where 匹配条件;
例如:删除name为张鑫的那一行
8.查询
语法:
select 列名 from 表名 where 匹配条件;
例如:
select name from haha where id >10;
查看显示结果集表 只看name这一列 在haha表中 id大于10的
select * from haha;
查看显示结果集表 所有列 在haha表中的所有 条件;
*表示所有列
9.数据库的匹配条件的提高版
例如:我们要进行使用用户名、密码进行登录,如果表中有你这个用户名且对应的密码一样,就可以让你登录
select *from haha where id =lanzhou and passwd = 123456;
如果你有显示,也就是查到东西了,这个时候你就可以登录了
常见的匹配条件:
in、and、or、between and、like模糊查找、not(取其补集)
where的高级用法:
in:
允许在where子句中规定多个值
语法:
where 列名称 in( 列值1,列值2,.....);
select *from haha where id in (1,2,3,4);
and:
多个条件结合起来,且
select *from haha where id =lanzhou and passwd = 123456;
or: 或
select *from haha where id =lanzhou or passwd = 123456;
between and:
between A and B,会选取A到B之间的数据
select *from haha where id between 1 and 3;
like:
模糊查找、像,一般用于地址、姓名
select *from haha where id like 3; select *from haha where addr like "%zhou%";
%zhou%表示你的地址中带有zhou的
%表示通配
例如:姓张的人 "张%"
名字带张就行 "%张%"
not:取补集
select *from haha where id not in (1,2,3,4);
排序:
根据指针的列结果集表进行排序
默认按照升序的进行排序的,可以使用关键字desc(降序)
升序:
select*from haha order by 列名;
降序:
select *from haha order by 列名 desc;
例如:
select *from haha order by id;
如何进行添加新的数据从一个旧的表中
insert into 新表 select 列名 from 旧表;
前提条件:当前的新表中有这个列名称及对应的数据类型
小练习:
1.打开一个名为haha的数据库
sqlite3 haha.db
2.新建一张数据表,表名为persons,拥有以下几列
id int , name text,addr text
create table persons (id int, name text, addr text);
3.向表内插入新的一列 sex text
alter table persons add sex text;
4.向表persons插入两行数据
id为10 name为qianfeng
id为12 name为haha addr为beijing
insert into persons (id,name) values (10,"qianfeng");
insert into persons values(12,"haha","beijing");
5.将persons表名更改为qianfeng
alter table persons rename to qianfeng;
6.将qianfeng表中id为12的行里面的addr设置为shandong
update qianfeng set addr = "shandong" where id = 12;
7.插入新的一行数据
id为15 name为xixi addr为beijing sex为man
alter table qianfeng add sex text; insert into qianfeng values(15,"xixi","beijing","man");
8.查看显示所有列,在qianfeng表中id大于10的
select * from qianfeng where id >10;
9.修改qianfeng表中,id在10到14之间的行中 addr 为zb
update qianfeng set addr = "zb" where id between 10 and 14;
10.删除qianfneg表中addr中带有字母n的所有行
delete from qianfeng where addr like "%n%";
数据库控制
我们的数据库一般都存放在我们的系统的内存上,以文件的形式
一般情况下对文件进行操作,主要有打开、读、写、关闭
我们对数据库的操作也是打开、读、写、关闭,只不过我们使用的是数据库库函数
1.对数据库打开操作:
SQLITE_API int sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
参数 :
你要打开的文件名,文件名是一个字符串,需要" "
数据库句柄的地址(指针)
以上函数表示的就是打开这个数据库文件,放入到句柄的中
因为你传递的参数是句柄的地址,因此我可以改变句柄的内容
返回值:
如果当前的函数成功运行,就会返回一个SQLITE_OK
编写代码之前我们需要进行一些准备工作:
1.需要保证当前的文件夹内有一个sqlite3.c 和sqlite3.h这两个文件
这个时候你就可以敲代码了
//1.包含头文件#include "sqlite3.h"#include int main(int argc, char const *argv[])
{
sqlite3 *db;//定义一个数据库句柄int ret = sqlite3_open("didi.db",&db);
if (ret != SQLITE_OK)
{
printf("打开数据库失败\n");
}
else
printf("打开数据库成功\n");
return 0;
}
2.对数据库关闭操作
SQLITE_API int sqlite3_close(sqlite3*);
参数:
数据库句柄db
返回值:
如果当前的函数成功运行,就会返回一个SQLITE_OK
编写代码:
//1.包含头文件#include "sqlite3.h"#include int main(int argc, char const *argv[])
{
sqlite3 *db;//定义一个数据库句柄int ret = sqlite3_open("didi.db",&db);
if (ret != SQLITE_OK)
{
printf("打开数据库失败\n");
}
else
printf("打开数据库成功\n");
ret = sqlite3_close(db);
if (ret != SQLITE_OK)
{
printf("关闭数据库失败\n");
}
else
printf("关闭数据库成功\n");
return 0;
}
3.对数据库写操作
SQLITE_API int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
参数:
打开的数据库句柄
sql语句字符串
同时调用的函数名称 一般写NULL
传递给函数的参数一般写NULL
错误信息的存储位置
返回值:
如果当前的函数成功运行,就会返回一个SQLITE_OK
代码编写:
#include #include "sqlite3.h"//包含数据库函数所在的头文件//因为sqlite3.c和.h都与当前文件为同一文件夹因此使用""int main(int argc, char const *argv[])
{
sqlite3*db;//创建一个数据库句柄dbint ret = sqlite3_open("haha.db",&db);//---------------打开//ret就是用来接返回值,如果函数正确的运行返回值就是//SQLITE_OKif (ret !=SQLITE_OK)
{
printf("数据库打开出错\n");
}
else
printf("数据库打开成功\n");
// 1.思考自己要做的操作:新建一个表//获取你需要的数据printf("请输入你要创建的表\n");
char table_name[50] = "";
scanf("%s",table_name);
// 2.写一个创建表的sql语句.//再去定义一个数组用来保存我重新组的新字符串char cmd[100] = "";
sprintf(cmd,"create table %s (id int ,name text);",table_name);//完成了一个组包的操作
// 3.看自己是读操作还是写操作// 如果是写操作就使用sqlite3_exec// 如果是读操作就使用sqlite3_get_table// 4.调用就行了char *errmsg = NULL;
sqlite3_exec(db,cmd,NULL,NULL,&errmsg);
if (errmsg != NULL)//如果我们出现错误就会打印errmsg{
printf("%s\n", errmsg);
}
ret = sqlite3_close(db);//-------------------------------关闭if (ret !=SQLITE_OK)
{
printf("数据库关闭出错\n");
}
else
printf("数据关闭成功\n");
return 0;
}
//编译gcc xxx.c sqlite3.c -lpthread -ldl
4.对数据库读操作
SQLITE_API int sqlite3_get_table(
sqlite3 *db, /* An open database */
const char *zSql, /* SQL to be evaluated */
char ***pazResult, /* Results of the query */
int *pnRow, /* Number of result rows written here */
int *pnColumn, /* Number of result columns written here */
char **pzErrmsg /* Error msg written here */
);
参数:
你打开的数据库句柄 --------也就是你要对哪个数据库进行读操作;
你要进行读操作的SQL语句(查)
查询到的结果集表的地址
你查到的结果集表的行数(查询到的数据行数)
你查到的结果集表的列数(查询到的数据列数)
错误信息
返回值:
如果当前的函数成功运行,就会返回一个SQLITE_OK
#include #include "sqlite3.h"int main(int argc, char const *argv[])
{
sqlite3*db;
int ret = sqlite3_open("xixi.db",&db);
if (ret !=SQLITE_OK)
{
perror("SQLITE_OK\n");
return 0;
}
char table_name[50] = "";
printf("请输入你要创建的表\n");
scanf("%s",table_name);
// 2.写一个创建表的sql语句.//再去定义一个数组用来保存我重新组的新字符串char cmd[100] = "";
sprintf(cmd,"create table %s (id int ,name text);",table_name);//完成了一个组包的操作
// 3.看自己是读操作还是写操作// 如果是写操作就使用sqlite3_exec// 如果是读操作就使用sqlite3_get_table// 4.调用就行了char *errmsg = NULL;
sqlite3_exec(db,cmd,NULL,NULL,&errmsg);
if (errmsg != NULL)//如果我们出现错误就会打印errmsg{
printf("%s\n", errmsg);
}
int id = 0;
char name[50] = "";
printf("请输入你的id\n");
scanf("%d",&id);
printf("请输入你的name\n");
scanf("%s",name);
char cmd2[100] = "";
sprintf(cmd2,"insert into %s values(%d,\'%s\');",table_name,id,name);// \'就相当于引号sqlite3_exec(db,cmd2,NULL,NULL,&errmsg);
if (errmsg != NULL)//如果我们出现错误就会打印errmsg{
printf("%s\n", errmsg);
}
char cmd3[100] = "";
sprintf(cmd3,"select name from %s where id = %d;",table_name,id);
char **table = NULL;//用来存放你数据库查到的结果int r,c;//r行数 c列数sqlite3_get_table(db, cmd3,&table,&r,&c,&errmsg);
if (errmsg != NULL)//如果我们出现错误就会打印errmsg{
printf("%s\n", errmsg);
}
printf("%s\n", table[1]);
//由于你只有1列,最上方的列名是table[0],因此你的name就是tabel[1]
char cmd4[100] = "";
sprintf(cmd4,"select * from %s; ",table_name);
sqlite3_get_table(db, cmd4,&table,&r,&c,&errmsg);
if (errmsg != NULL)//如果我们出现错误就会打印errmsg{
printf("%s\n", errmsg);
}
int i,k;
for (i = 0; i < r+1; ++i)//r+1是因为多出来一个列名一行{
for (k = 0; k < c; ++k)
{
printf("%s", table[i*c+k]);
}
printf("\n");
}
printf("\n");
sqlite3_close(db);
return 0;
}
使用实例:
1.需求流程
首先让你输入一个表名
按照你的表名去创建一个新的表,id int ,name text 两列
让你输入id和name
然后插入到你这个刚刚建立的表中
然后查询你刚刚输入的id对应的名字
2.心理变化
我不管干嘛,只要对数据库操作就先打开数据库
获取键盘输入的表名
组一个创建表的sql语句(这个语句是一个写操作)
使用写的操作去向数据库发送--sqlite3_exec
因为后面还用数据库因此不关数据库
获取键盘输入的id和name
组一个插入新的一行的sql语句(这个语句是一个写操作)
使用写的操作去向数据库发送--sqlite3_exec
因为后面还用数据库因此不关数据库
组一个查询的sql语句查name匹配id(这个语句是一个读操作)
使用读的操作去向数据库发送--sqlite3_get_table
打印读取到的内容
关闭数据库
代码:
#include
#include "sqlite3.h"
int main(int argc, char const *argv[])
{
sqlite3*db; int ret = sqlite3_open("xixi.db",&db); if (ret !=SQLITE_OK) { perror("SQLITE_OK\n"); return 0; } char table_name[50] = ""; printf("请输入你要创建的表\n"); scanf("%s",table_name); // 2.写一个创建表的sql语句. //再去定义一个数组用来保存我重新组的新字符串 char cmd[100] = ""; sprintf(cmd,"create table %s (id int ,name text);",table_name);//完成了一个组包的操作 // 3.看自己是读操作还是写操作 // 如果是写操作就使用sqlite3_exec // 如果是读操作就使用sqlite3_get_table // 4.调用就行了 char *errmsg = NULL; sqlite3_exec(db,cmd,NULL,NULL,&errmsg); if (errmsg != NULL)//如果我们出现错误就会打印errmsg { printf("%s\n", errmsg); } int id = 0; char name[50] = ""; printf("请输入你的id\n"); scanf("%d",&id); printf("请输入你的name\n"); scanf("%s",name); char cmd2[100] = ""; sprintf(cmd2,"insert into %s values(%d,\'%s\');",table_name,id,name);// \'就相当于引号 sqlite3_exec(db,cmd2,NULL,NULL,&errmsg); if (errmsg != NULL)//如果我们出现错误就会打印errmsg { printf("%s\n", errmsg); } char cmd3[100] = ""; sprintf(cmd3,"select name from %s where id = %d;",table_name,id); char **table = NULL;//用来存放你数据库查到的结果 int r,c;//r行数 c列数 sqlite3_get_table(db, cmd3,&table,&r,&c,&errmsg); if (errmsg != NULL)//如果我们出现错误就会打印errmsg { printf("%s\n", errmsg); } printf("%s\n", table[1]); //由于你只有1列,最上方的列名是table[0],因此你的name就是tabel[1] char cmd4[100] = ""; sprintf(cmd4,"select * from %s; ",table_name); sqlite3_get_table(db, cmd4,&table,&r,&c,&errmsg); if (errmsg != NULL)//如果我们出现错误就会打印errmsg { printf("%s\n", errmsg); } int i,k; for (i = 0; i < r+1; ++i)//r+1是因为多出来一个列名一行 { for (k = 0; k < c; ++k) { printf("%s", table[i*c+k]); } printf("\n"); } printf("\n"); sqlite3_close(db); return 0; }
你查询得到的是一张表,有行有列的
如何进行数据库代码的编写:
1.看自己需要进行什么操作;
收集一下自己需要到的变量(数据)
2.组一个操作的字符串(sql语句)
3.打开数据库
4.思考我们当前的数据库操作是读还是写(增删改都是写操作,读就是查操作)
5.对应的调用一下函数将自己的sql语句发给数据库
6.看一下自己还要进行什么操作
7.关闭数据库
如何组包:
1.收集好自己要往包中组的数据
2.开始组包
为什么要传递&取地址:
传递取地址都是指针传递(参数的传递):可以更改其内容
我们使用代码验证一下:
如何排错:
1.看函数的返回值,如果函数的返回值是SQLITE_OK就说明当前函数运行的没有问题
如果有问题,打印一下错误信息 perror("sqlite3_open\n");
2.如果你的返回值是SQLITE_OK,如果还是有问题,这个时候我就去看errmsg
也就是,如果你的sql语句出问题,你出了什么问题就会在errmsg中进行存储
printf("%s\n",errmsg);
感谢小伙伴对鑫哥的大力支持,谢谢