当前位置: 首页 > news >正文

SQLite3数据库——Linux应用

一、简介

SQLite 是一款轻型、遵守 ACID嵌入式关系型数据库引擎,由 D. Richard Hipp 于 2000 年发布并置于公有领域。

  • 整个引擎仅一个 C 库,编译后< 1 MB,运行时< 64 kB RAM即可工作。

  • 支持 Windows/Linux/Unix 及 Tcl、C#、PHP、Java、ODBC 等主流语言绑定。

  • 单连接、低并发、简单查询场景下性能优于 MySQL/PostgreSQL;高并发场景则相反。

  • 截至 2025 年 6 月,最新稳定版为 3.49.1,项目已持续活跃 25 年。

数据库的用途数据的存取。主要就是对表中的数据 增 、删 、查、改

1.1 SQLite3安装

核心:sudo apt-get install sqlite3 libsqlite3-dev(安装数据库)
如果安装失败,先尝试如下指令:
         sudo apt-get update(更新软件源)
         sudo apt-get install -f(更新软件依赖)

验证安装成功的方法:
终端输入命令:sqlite3将进入到sqlite3命令行

1.2 数据库、表、记录(元组)、属性

数据库:一系列数据类型的集合(图、表、二叉树、线性表.....),每个数据库存在数据库名, 通常以  xxxx.db  作为后缀
: 数据库下具体的一种数据类型,可以存在多张表(类比excl),每张表 存在 表名
关系: 一种关系对应一张表
元组:表中的一行或者一条记录
属性:表中的一列叫做一个属性,给每一个属性起一个具体的名称,就是属性名

二、常用操作

命令操作(注意前方的.
.help:查看帮助信息,列出所有的系统命令
.exit:退出数据库
.quit:退出数据库
.databases:查看当前数据库信息
.tables:列出当前数据库中所有表的名字
.schema:列出数据库中所有表的结构

2.1 创建数据库

方式一:sqlite3   xxx.db       若文件不存在就创建并打开 xxx.db,成为 main 数据库
方式二:sqlite3
.open   xxx.db         先启sqlite3,若文件不存在就创建并打开

方式三:  sqlite3
.open   xxx.db
.attach database 'xxx.db' as xxx;  连续创建多个数据库

在 SQLite 里,main 数据库就是你当前用 .open 打开(或命令行指定)的那个物理文件,所有不带模式前缀的表、索引、视图都默认创建在这个main数据库里.

注意:当退出sqlite时再次启动并进入数据库后再次.databases,只会出现打开的那个库(ATTACH 附加的数据库只在当前会话生效;一旦 .quit 退出,所有附加库自动 DETACH,下次再进就只剩 main 了

2.2 创建表

方式一:create table 表名 (属性名 数据类型,属性名 数据类型,……);
方式二:create table if not exists 表名 (属性名 数据类型,属性名 数据类型,……);
例如:create table if not exists stu(id int,name char,sex char,score int);
创建表格的核心部分是create table 表名
if not exists  译为“如果不存在,则……”(可省略)
stu 是本例中表格的名字
(id int,name char,sex char,score int);是用于指定表格中各项属性,每个属性之间用逗号隔开。且每个属性采用格式: “属性名  数据类型” 属性数量自定义(注意末尾的分号)

会话里除了你自己的 stu.db(main)之外,SQLite 还为你准备好了 temp 这块“草稿纸”,随时可用

删除表:drop table if exists stu

存储类含义 (SQLite 只有 5 个原生存储类)
integer整数(1/2/3/4/6/8 字节自动变长)
real8 字节 IEEE 浮点
textUTF-8/UTF-16 字符串
blob二进制数据(原样保存)
null空值

2.3 往表格中插入记录

方式一:insert into 表名 (所有属性名并逗号隔开)  values (依次按数据类型全部赋值并逗号隔开);
方式二:insert into 表名 (部分属性名并逗号隔开)  values (依次按数据类型部分赋值并逗号隔开);
方式三:insert into 表名  values (依次按数据类型全部赋值并逗号隔开);
方式四:insert into 表名 values (依次按数据类型全部赋值并逗号隔开),(依次按数据类型全部赋值并逗号隔开), (依次按数据类型全部赋值并逗号隔开);

例:

2.4 查询表中记录

方式一:select *from 表名;查找表中的所有数据
方式二:属性名 from 表名;查找表中的指定N个属性名的数据

过滤并查询表中记录:

方式一:select * from  表名 where 属性名=属性值; 

               查询表中属性值对应的所有数据

方式二:select * from  表名 where 属性名=属性值  and  属性名=属性值;

               查询表中属性值对应的所有数据--并列都满足的条件

方式三:select * from  表名 where 属性名=属性值  or 属性名=属性值;
查询表中属性值对应的所有数据--任意满足一个的条件

*可以理解为通配符,哪些列

select要“选列”,所以用 *、where 限定"行"

2.5 删除表中记录

方式一:delete  from 表名 where 属性名=属性值;
删除属性名对应的属性值的记录
方式二:delete from  表名;
把表所有数据都删除
方式三:delete  from 表名 where 属性名=属性值  and 属性名=属性值 ;
方式四:delete  from 表名 where 属性名=属性值  or 属性名=属性值 ;

delete只“删行”,无需列名,因此没有 *、where 限定"行"

2.6 更新记录属性

方式一:update 表名 set 要修改的属性名=要修改的属性值 where 依据属性名=属性值;
修改对应的属性中的属性值
方式二:update  表名 set 要修改的属性名=要修改的属性值;
修改属性名中的所有属性值

2.7 添加属性(添加列)

方式一:alter table 表名 add column 属性名 属性类型;

2.8 删除属性(删除列)

SQLite3不允许直接删除一列,
可用三个步骤代替:
1.基于原表中部分属性,创造出一个新表(新表中的属性种类可以少于原表,相当于删除一些列)
2.删除原表
3.将新表重命名,修改为和原表相同

1.create table stu1 as select num,name,sex from stu;
基于表stu中的id、name和sex属性创建出一个新表stu1(复制记录)
2.drop table stu;
从数据库文件中删除表stu
3.alter table stu1 rename to stu;
将表stu1重命名为stu

2.9 主键值

对于具有特定用途的表,表中通常存在一种或多种属性是每条记录不允许重复的。(比如:存储QQ账号的表,要求每条记录中QQ的ID号要互不相同;存储居民信息的表,要求每条记录中的身份号要互不相同……)
对于这类属性,可以在创建表的时候指定这种属性为主键值,则之后对于表格进行操作时,新增的任何记录中的主键值属性都不能相同,若相同,则操作失败。

主键值用法:

创建表时指定属性为主键值。

create table stu(id int primary key, name text, password text);

三、相关API

3.1  sqlite3_open/sqlite3_open_v2 函数

函数原型:int sqlite3_open(const char *filename,sqlite3** ppDb)
函数功能:打开一个数据库文件,如果文件不在则创建一个数据库并打开
函数参数:
@param1
:filename 数据库文件的名字(考虑路径), 数据库名字后缀 .db
特殊值:
     :memory: - 创建内存数据库(临时,连接关闭后销毁)
空字符串“”- 创建临时磁盘数据库(连接关闭后自动删除)
NULL - 创建临时内存数据库
 常规文件名-开或创建磁盘上的数据库文件
   @param2:ppdb     传出操纵数据库的二级指针,相当于句柄。
返回值:成功:返回SQLITE_OK;失败:error_code 可以通过sqlite3_errmsg获取错误信息
注意:无论打开数据库成功与否,都需要关闭

函数原型:int sqlite3_open_v2(const char*filename,sqlite3**ppDb,int flags,const char*zVfs)

函数功能:以某种方式打开或者创建数据库

函数参数:
@param1
:filename 数据库文件的名字(考虑路径), 数据库名字后缀 .db
特殊值:
     :memory: - 创建内存数据库(临时,连接关闭后销毁)
空字符串“”- 创建临时磁盘数据库(连接关闭后自动删除)
NULL - 创建临时内存数据库
 常规文件名-开或创建磁盘上的数据库文件
   @param2:ppdb    传出操纵数据库的二级指针,相当于句柄。

   @param3:flags    打开标志

             SQLITE_OPEN_READWREITE   读写方式打开
SQLITE_OPEN_CREATE            不存在则创建
SQLITE_OPEN_READONLY       只读的方式打开
SQLITE_OPEN_FULLMUTEX     启用线程安全
   @param4:VFS名称(通常为NULL)

返回值:成功:返回SQLITE_OK;失败:error_code 可以通过sqlite3_errmsg获取错误信息

3.2 sqlite3_close/sqlite3_close_v2函数

函数原型:int sqlite3_close(sqlite3* pDb)
函数功能:关闭一个数据库
函数参数: pdb:操纵数据库的一级指针,句柄。
返回值:成功:返回SQLITE_OK, 失败:error_code 可以通过sqlite3_errmsg获取错误信息

函数原型:int sqlite3_close_v2(sqlite3 *db);
函数功能:关闭数据库(推荐)

3.3 sqlite3_exec 函数

函数原型:int sqlite3_exec(sqlite3* pDB, const char *sql, sqlite_callback callback, void*para, char** errMsg);
函数功能:对指定的数据库文件执行sql规定的指令。若这条指令能返回数据,则触发执行回调函数。
函数参数:
@param1:  
pDB  填sqlite3_open()的第二个参数,操作数据库的指针
   @param2:  sql    填待执行的数据库指令(注意:字符串形式、尤其注意引号的使用--当执行指令中存在""时,需要把""使用 \”  转义)
举例: "create table if not exists stu(id int primary key, name text, password text);"
   @param3:  callback   函数指针,指向一个回调函数.(如果是增删改操作,不需要用到回调函数,该参数可以填NULL; 如果是查询等操作,需要用到回调函数)
   @param4:  para  作为callback对应回调函数的实参
@param5:   errMsg    输出参数:返回错误信息
返回值:执行成功返回 SQLITE_OK,否则返回其他值

回调函数:callback 回调函数的执行规则,sqlite3_exec()每查询到一条记录,基于这条记录执行一次回调函数

函数原型:typedef int (*sqlite_callback)(void* para,int columnCount,char** columnValue,char** columnName);

函数功能:由用户处理查询的结果

函数参数:
@param1:para 接收 sqlite3_exec()传入的第4个参数para;

    @param2:columnCount, 查询到的这一条记录有多少个字段 (即这条记录有多少列);

    @param3:columnValue,一个指针数组,查询出来的数据都保存在这里,它实际上是个 1 维数组(不要以为是 2 维数组),每一个元素都是一个 char * 值,是一条记录的内容(用字符串来表示,以‘\0’结尾);

   @param4:columnName,与 columnValue 是对应的,表示记录对应的属性名称。

举例:

int ret      ;
char* errMsg ;
sqlite3 *qDB ; //用于指向待操作的数据库文件	//查询并显示表中数据(会用到回调函数 --> 帮助显示表中的记录)	
strcpy(action, "select * from QQ;");
ret = sqlite3_exec(qDB, action, print_record, NULL, &errMsg);
if(ret != SQLITE_OK)
{perror("select error!\n");return -1;
}/*
假设表中数据如下:
12345|zhangsan|111
23456|lisi    |222
34567|wangwu  |333现在查询表中数据,执行指令select * from QQ;
那么回调函数会执行3次:
第1次执行,columnCount = 3,数组columnValue有3个元素"12345","zhangsan","111", 数组columnName有3个元素"id","name","password"
第2次执行,columnCount = 3,数组columnValue有3个元素"23456","lisi,"222", 数组columnName有3个元素"id","name","password"
第3次执行,columnCount = 3,数组columnValue有3个元素"34567","wangwu,"333", 数组columnName有3个元素"id","name","password"
*///将作为sqlite3_exec()的回调函数,执行查询表的指令时:每获取到一条记录,自动执行一次该函数
// sqlite3_exec的参数para;有多少列(属性/字段);char*数组,存所有属性的值;char*数组,存属性的名字
int print_record(void* para,int columnCount,char** columnValue,char** columnName)
{static int cnt = 0;cnt++;printf("No.%d record! ", cnt);for(int i = 0 ;i < columnCount; i++){printf("%s = %s  ", columnName[i], columnValue[i]);}printf("\n");//需要提供返回值!return 0;
}

3.4 获取/释放表中数据 

函数原型:int sqlite3_get_table(sqlite3* pDB, const char *sql,char ***pResult, int * rowCount,int * columnCount, char** errMsg);
函数功能:执行 SQL 语句,通过一维数组返回结果;一般用于数据记录查询
函数参数:
输入参数:

@param1:pDB,打开的数据库句柄;
    @param2:  sql,待执行的 SQL 字符串,以’ \0’结尾;
输出参数
@param3:pResult,查询结果,是由字符串组成的一维数组(不要以为是二维数组,更不要以为是三维数组)。它的内存布局是:第一行是字段(属性)名称,后面紧接着每个字段的值;
    @param4:rowCount,查询出多少条记录(即查出多少行);
    @param5:columnCount,查询出来的记录有多少个字段(多少列);
    @param6:errMsg,返回错误信息;
返回值:执行成功返回 SQLITE_OK,否则返回其他值

函数原型:void sqlite3_free_table(char **result);

函数功能:释放查询结果占用的内存;

输入参数:result, 通过函数 sqlite3_get_table()查询到的记录结果;

输出参数:无

返回值:无

char ** pResult;
int row, column;sqlite3_get_table(qDB, "select * from QQ;", &pResult, &row, &column, &errMsg);printf("row = %d, column = %d\n", row, column);
for(int i = 0; i< (row + 1) * column; i++)//之所以 row+1 还要算上 第一行的属性
{printf("%s, ", pResult[i]);
}sqlite3_free_table(pResult);/**************【或】*******************/
printf("row = %d, column = %d\n", row, column);// 打印表头(第一行)
for(int i = 0; i < column; i++)
{printf("%-10s", pResult[i]);
}
printf("\n");// 打印数据行
for(int i = 1; i <= row; i++)
{for(int j = 0; j < column; j++){printf("%-10s", pResult[i * column + j]);}printf("\n");
}

四、代码

gcc mysqlite3.c -lsqlite3 -o mysqlite3 
/*编写函数:
1.创建一个数据库,创建一个4属性表
2.插入3行记录
3.使用回调函数,输出指定 name="李四"的该行信息
4.修改 name="张三" 该行记录中  id 改为 2
5.使用获取表中数据函数,得到标志所有信息
6.删除表
7.关闭数据库*/#include<stdio.h>
#include<stdlib.h>
#include<sqlite3.h>
#include<string.h>int print_record(void* para,int columnCount,char** columnValue,char** columnName){static int cnt = 0;cnt++;printf("No.%d record! ", cnt);for(int i = 0 ;i < columnCount; i++){printf("%s = %s  ", columnName[i], columnValue[i]);}printf("\n");return 0;}int main()
{/*1.创建一个数据库*/int ret;sqlite3* handler_stu;char* errMsg=NULL;ret = sqlite3_open("./student.db",&handler_stu);  if(ret!=SQLITE_OK){printf("sqlite3_open error:%s\n",sqlite3_errmsg(handler_stu));sqlite3_close(handler_stu);return -1;}/*2.创建一个四属性表格*/char action[1024];strcpy(action,"create table if not exists stu(id int,name char,sex char,score int);");ret = sqlite3_exec(handler_stu,action, NULL, NULL, &errMsg);if(ret!=SQLITE_OK){printf("sqlite3_exec create table error:%s\n",errMsg);sqlite3_free(errMsg);sqlite3_close(handler_stu);return -2;}memset(action,0,sizeof(action));/*3.插入一些数据*/strcpy(action,"insert into stu values(1114,\"张三\",\"M\",123),(1115,\"李四\",\"M\",150),(1116,\"王五\",\"W\",100);");ret = sqlite3_exec(handler_stu,action, NULL, NULL, &errMsg);if(ret!=SQLITE_OK){printf("sqlite3_exec insert error:%s\n",errMsg);sqlite3_free(errMsg);sqlite3_close(handler_stu);return -3;}memset(action,0,sizeof(action));/*4.使用回调函数,输出指定 name="李四"的该行信息*/printf("=== 查询李四的信息 ===\n");strcpy(action,"select * from stu where name = \"李四\";");ret = sqlite3_exec(handler_stu,action, print_record, NULL, &errMsg);if(ret!=SQLITE_OK){printf("sqlite3_exec select error:%s\n",errMsg);sqlite3_free(errMsg);sqlite3_close(handler_stu);return -4;}memset(action,0,sizeof(action));/*5.修改 name="张三" 该行记录中  id 改为 2*/strcpy(action,"update stu set id = 2 where name=\"张三\";");ret = sqlite3_exec(handler_stu,action,NULL, NULL, &errMsg);if(ret!=SQLITE_OK){printf("sqlite3_exec updata error:%s\n",errMsg);sqlite3_free(errMsg);sqlite3_close(handler_stu);return -5;}memset(action,0,sizeof(action));/*6.使用获取表中数据函数,得到标志所有信息*/printf("\n=== 获取表中所有信息 ===\n");char **pResult;//查询的结果int row       ;//总行数,不算上属性int column    ;//总列数ret = sqlite3_get_table(handler_stu,"select*from stu;",&pResult,&row,&column,&errMsg);if(ret!=SQLITE_OK){printf("sqlite3_get_table error: %s\n", errMsg);sqlite3_free(errMsg);sqlite3_close(handler_stu);return -6;}printf("row = %d, column = %d\n", row, column);// 打印表头(第一行)for(int i = 0; i < column; i++){printf("%-10s", pResult[i]);}printf("\n");// 打印数据行for(int i = 1; i <= row; i++){for(int j = 0; j < column; j++){printf("%-10s", pResult[i * column + j]);}printf("\n");}sqlite3_free_table(pResult);//释放表中数据/*删除表*/memset(action,0,sizeof(action));strcpy(action,"drop table if exists stu;");  ret = sqlite3_exec(handler_stu,action,NULL, NULL, &errMsg);if(ret!=SQLITE_OK){printf("sqlite3_exec drop error:%s\n",errMsg);sqlite3_free(errMsg);sqlite3_close(handler_stu);return -7;}sqlite3_close(handler_stu);printf("数据库操作完成!\n");return 0;
}

http://www.dtcms.com/a/477819.html

相关文章:

  • 人机关系中“看不见的手”
  • 上街区网站建设做网站用什么系统好
  • k8s cert-manager cert-manager-webhook-xxx pod 证书过期问题处理
  • 宝塔服务器磁盘爆满:占用50G磁盘空间的.forever日志文件处理导致服务崩溃的教训
  • Docker资源限制全解析
  • 毫米级的安全舞蹈
  • 成都网站专业制作一造和一建哪个难度大
  • 解码AI智能体的大脑:Function Calling 与 ReAct 策略深度对决
  • K8s多租户方案指南--图文篇
  • 去一个新公司~重新设置git信息,clone项目 ~需要做的
  • wordpress 自动标签插件廊坊seo推广
  • Abase 数据库:永久关闭 misopt_preventing 选项的方法
  • 基于单片机的智能洗碗机设计
  • 网站策划书ppt9377白蛇传奇
  • 从Wireshark到Mitmproxy:网络数据侦探——抓包工具在爬虫开发中的艺术与科学之“HTTPS全流量解密实战”
  • HTTP与HTTPS的五大核心区别
  • 关于2025.10.13力扣每日的学习
  • Hive 删除分区语句卡死问题
  • 19.1 TCP 和 UDP 有什么区别?
  • 汇编和C语言结构
  • 单页网站的营销高端渠道开发
  • 定制网站建设公司哪家便宜seo免费课程
  • 【密码学实战】openHiTLS server命令行:搭建国密标准安全通信服务器
  • AWS RDS (MySQL)蓝绿部署常见误区
  • 工信部发布→《云计算综合标准化体系建设指南(2025版)》
  • K8S重启引发的RocketMQ消息丢失问题记录
  • K8S(七)—— Kubernetes Pod 进阶配置与生命周期管理全解析
  • 主题库 1.15 | 提供风景、动漫、明星、动物等多种类型的高清壁纸,轻松更换手机壁纸
  • 百度云自助建站用微信做网站
  • 免费自助小型网站怎么制作链接视频教程