一种轻量级的关系型数据库管理系统,可以在应用程序中作为一个单独的组件运行,因此也被称为嵌入式数据库。与传统的客户端-服务器架构不同,SQLite 数据库存储在单个文件中,并直接与应用程序交互。它不需要专门的服务器进程或守护进程,也不需要网络通信,因此非常适合用于移动设备、桌面应用程序或其他小型嵌入式环境。
SQLite 使用 C API 进行访问,可以轻松地集成到任何支持 C 语言的环境中。它还提供了多种语言绑定,包括 Python、Java、PHP、Ruby 等,使得在这些语言中使用 SQLite 更加容易。 是一种高效、易用的嵌入式数据库解决方案,特别适合在资源有限的环境中使用。
SQLite 和 MySQL 都是非常流行的关系型数据库管理系统,但它们之间存在一些重要的差异:
1. 架构差异:MySQL 是一种典型的客户-服务器架构,由服务器进程来管理和处理所有数据库请求;而 SQLite 则没有独立的服务器进程,所有的操作都在客户端完成,可以直接与应用程序交互。
2. 大小和性能差异:MySQL 提供了许多高级特性,例如表分区、索引优化等,而且能够处理大规模的数据集;而 SQLite 则更加简单和紧凑,更适合小规模的应用程序和嵌入式环境。
3. 安全性和可靠性:MySQL 支持复杂的权限控制和安全机制;而 SQLite 主要依赖于操作系统和文件系统的安全措施。
总体来说,MySQL 更适合高性能、高并发的大规模应用,而 SQLite 则更适合资源受限的小型应用或嵌入式系统。
找不到相关内容说明没有安装过
一般sqlite3的使用场景更多,运行“sudo apt-get -y install sqlite3”
sudo apt-get -y install sqlite3
运行“sudo apt-get -y install sqlite” ,此时的版本是2.8.17,大家直接装sqlite3
运行上面指令时报错E:dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem.
“dpkg 已经被打断,您必须手动运行 'sudo dpkg --configure -a' 来纠正这个问题。” 这通常意味着你的 Ubuntu 系统正在尝试安装软件包的过程中遇到了某种错误,导致 dpkg (Debian 包管理器)无法正常工作。
按提示输入'sudo dpkg --configure -a'
再次输入安装指令
完成后输入 sqlite3 查看
输入 .quit 可退出
在工作目录“/home/orangepi/”下创建一个文件夹,将数据库文件存放在这里:
在刚刚创建的文件夹里面
执行“.open A.db”时,如果一个数据库A.db不存在则会创建并打开;若该数据库已经存在就会打开;且 “.open A.db”不是SQL命令,对应的C接口是sqlite3_open( )函数
在刚刚创建的文件夹里面
数据库表格的创建和结构体很类似,在实际中也经常将两者进行转换:
create table sf(age Integer,name char,height Integer); //在这里“int”应该写成“Integer”,且写在变量名的后方
打开刚刚创建的test.db数据库,并在其中添加一张名为sf的表格,表格有三个字段:整型的age和height,char型的name
执行“create table AA(....)”时,如果表AA不存在则会创建并打开;若表格已经存在则会报错;且 “create table AA(....)”是SQL命令,对应的C接口是sqlite3_exec( )函数
insert into sf values(18,'cxk',180);
//也可以此一次只插入部分的字段内容,比如只插入name和score,不插入id
insert into sf(name,height) values('jg',190); //插入部分字段内容
select * from sf; //查询所有字段的结果
select name,score from sf; //查询数据库中部分字段的内容
delete from sf where name = cxk;
update stu set name = 'majia' where score = 77;
alter table stu add column sex char;
drop table stu;
当输入了无法识别的指令,数据库会进入“...>”的状态:
输入“CTRL + Z” 就可以强制退出:
在学习了SQlite的基本操作之后,虽然有能力进行数据基本的增删改查,但是都需要输入“sqlite3”在数据库命令行来执行,我们希望实现的是更自动化的运行,比如程序在获取数据后可以自动写入数据库,这就需要学习如何打开/创建数据库的C接口:
sqlite3_open(const char *filename, sqlite3 **ppDb)
该指令打开一个指向 SQLite 数据库文件的连接,返回一个用于其他 SQLite 程序的数据库连接对象。
sqlite3_close(sqlite3*)
该指令关闭之前调用 sqlite3_open() 打开的数据库连接。
所有与连接相关的语句都应在连接关闭之前完成。 如果还有查询没有完成,sqlite3_close() 将返回 SQLITE_BUSY 禁止关闭的错误消息。
const char *sqlite3_errmsg(sqlite3*);
该指令通常用来获取最近调用的API接口返回的错误代码
错误代码:
test1.c
#include
#include
#include
int main(int argc, char** argv)
{
sqlite3 *db;
char *zErrMsg = 0;
int ret;
if(argc < 2){
printf("Usage: %s xxx.db\n",argv[0]);
return -1;
}
ret = sqlite3_open(argv[1], &db);
if(ret != SQLITE_OK){
printf("Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
printf("Opened database successfully\n");
}
sqlite3_close(db);
printf("close database\n");
}
编译运行,gcc编译需要链接sqlite3的库,执行a.out时给程序指定数据库test.db
如果test.db本来就存在,那么“./a.out test.db” 也会成功运行,只不过从“创建test.db并关闭”变成了“打开test.db并关闭”
`sqlite3_exec()` 是 SQLite 的一个内置函数,用于在指定的数据库连接上执行一个或多个 SQL 语句,并返回结果。它可以用于执行任何合法的 SQL 语句,包括 SELECT、INSERT、UPDATE 和 DELETE 等等。
使用 `sqlite3_exec()` 可以简化 SQLite 应用程序中的代码编写和维护工作,因为开发者只需要调用这个函数来执行 SQL 语句,而无需手动解析和处理查询结果。
此外,由于 `sqlite3_exec()` 支持回调函数,因此它还可以用于处理复杂的查询结果集。例如,当执行一个 SELECT 语句时,可以通过提供一个回调函数来处理每一行数据,以便实现更加灵活的数据处理方式。
sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void *data, char **errmsg)
其中:
该函数返回 SQLITE_OK(表示成功)、SQLITE_ERROR、SQLITE_INTERNAL、SQLITE_PERM、SQLITE_ABORT 等等,具体取决于操作的结果。
int callback(void *arg, int column_size, char *column_value[], char *column_name[])
用于处理 SQLite 查询结果的回调函数。当使用 sqlite3_exec()
执行包含 SELECT 语句或其他需要获取查询结果的操作时,可以将此回调函数作为参数传递给该函数。
实现查看数据库记录指令 sqlite3_exec(db, "select * from sf;", callback, 0, &zErrMsg);
#include
#include
#include
int callback(void *arg, int column_size, char *column_value[], char *column_name[])
{
int i;
printf("arg=%s\n",(char *)arg);
for(i=0;i
编译运行,gcc编译需要链接sqlite3的库,执行a.out时给程序指定查看的数据库test.db
#include
#include
#include
int callback(void *arg, int column_size, char *column_value[], char *column_name[])
{
int i;
printf("arg=%s\n",(char *)arg);
for(i=0;i
对于上一步创建的company表格,更新它的地址,然后删除这条记录
#include
#include
#include
int callback(void *arg, int column_size, char *column_value[], char *column_name[])
{
int i;
printf("arg=%s\n",(char *)arg);
for(i=0;i
由于表格已经存在,所以创建表格的命令出错了,不过由于我的修改,代码会继续运行而不是直接exit;更新数据后,地址的确改变了;而删除数据后,由于本来就只有一条记录,所以此时company表没有数据,所以此时哪怕调用了“select * from company;” sqlite3_exec函数也不会调用callback来打印信息!
!!回归正题!!
https://pan.baidu.com/s/1KDznkE5dkpjBGxTbj9HnzQ
提取码:sail
void create_db(){//创建/打开数据库并创建一个名为history的表格
int ret;
char *create_table_sql;
//打开数据库
ret = sqlite3_open("history.db", &db);
if(ret != SQLITE_OK){
printf("Can't open database: %s\n", sqlite3_errmsg(db));
exit(0);
}else{
printf("Open database successfully\n");
}
//创建表格
//create_table_sql = "create table history(cause char,count Integer);";
create_table_sql = "CREATE TABLE HISTORY(" \
"CAUSE CHAR(30) PRIMARY KEY NOT NULL," \
"COUNT INT NOT NULL );" ;
ret = sqlite3_exec(db, create_table_sql, callback, 0, &zErrMsg);
if(ret != SQLITE_OK){
printf("Can't create table: %s\n", sqlite3_errmsg(db));
//exit(0);
}else{
printf("Table create successfully\n");
}
}
void init_table() //用于初始化数据库中表格的值
{
char *init_table_sql;
int ret;
init_table_sql = "insert into history values('socket',0);";
ret = sqlite3_exec(db, init_table_sql, callback, 0, &zErrMsg);
if(ret != SQLITE_OK){
printf("Can't init table value: %s\n", sqlite3_errmsg(db));
}
init_table_sql = "insert into history values('sound',0);";
ret = sqlite3_exec(db, init_table_sql, callback, 0, &zErrMsg);
if(ret != SQLITE_OK){
printf("Can't init table value: %s\n", sqlite3_errmsg(db));
}
}
在上一节将数据存储到文件中我们创建了一个线程record,这一节我们将指令来源和次数保存到数据库中(SQLite)、指令来源和发出时间以及垃圾类型保存在文件中这两个步骤都放到record里面运行
分别写两个函数功能是将数据写入文件和数据库
void data_file() //将历史记录写入文件的函数
{
int hist_fd; // file description
int ret;
hist_fd = open("./history.txt",O_RDWR|O_CREAT|O_APPEND, 0666); //可读可写可打开的打开历史记录的文件,不存在就创建,且每次都追加写入
if(hist_fd < 0){
printf("fail to open history file!\n");
fflush(stdout);
}
ret = write(hist_fd, &hist_whole, strlen(hist_whole));
if(ret == -1){
printf("fail to write history write to file!\n");
fflush(stdout);
}else{
printf("write history to file successfully!\n");
//文件内数据和数据库里面的数据一起显示有点乱我就先注释掉了
/*printf("write the following history to file:\n");
printf("------------------------\n");
printf("%s",hist_whole);
printf("------------------------\n");*/
fflush(stdout);
}
close(hist_fd);
memset(hist_whole,'\0',sizeof(hist_whole)); //清空hist_whole!
}
void data_sql() //将历史记录写入数据库的函数
{
char update_sql[128] = {'\0'};
int ret;
// printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);
sprintf(update_sql,"update history set count = %d where cause = 'socket';",sock_cmd);//客户端指令
//printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);
ret = sqlite3_exec(db, (const char *)update_sql, callback, 0, &zErrMsg);
if(ret != SQLITE_OK){
printf("Can't update date: %s\n", sqlite3_errmsg(db));
}
sprintf(update_sql,"update history set count = %d where cause = 'sound';",sond_cmd);//语音指令
ret = sqlite3_exec(db, (const char *)update_sql, callback, 0, &zErrMsg);
if(ret != SQLITE_OK){
printf("Can't update date: %s\n", sqlite3_errmsg(db));
}
ret = sqlite3_exec(db, "select * from history;", callback, 0, &zErrMsg); //将数据库数据打印到屏幕
if(ret != SQLITE_OK){
printf("Can't show date: %s\n", sqlite3_errmsg(db));
}
//清零
int sock_cmd = 0;//客户端指令
int sond_cmd = 0;//语音指令
}
将这两个函数在线程record里面调用
我们统计指令来源(客户端、语音模块)在对应触发语句将各自变量+1