数据库
1.数据库:能够对大批量数据进行增删改查的软件
2.数据库的分类:
1.关系型数据库
1.将数据存放在文件中
Oracle, MySql, SQlite
2.非关系数据库
1.将数据存放在内存中,内存数据库
Redis, Nosql
安装sudo apt-get install sqlite3
使用
进入:sqlite3 test.db 创建test.db文件
这些命令在 sqlite> 交互式环境中使用,不需要以分号结尾。
.help 显示所有可用命令的帮助信息 .help
.exit 或 .quit 退出 SQLite 交互式环境 .exit
.tables 显示当前数据库中的所有表 .tables *
.schema 显示表的创建语句(结构) .schema 表名
.databases 显示当前打开的数据库文件路径 .databases *
.indices 显示表的所有索引 .indices 表名
.dump 导出整个数据库为 SQL 脚本 .dump > backup.sql
.read 执行外部 SQL 脚本文件 .read script.sql
.output 将输出重定向到文件 .output result.txt
.mode 设置查询结果的显示模式 .mode column 或 .mode csv *
.headers on/off 显示/隐藏查询结果的列名 .headers on *
.nullvalue 设置 NULL 值的显示字符 .nullvalue NULL
.show 显示当前的设置状态 .show
.schema 查看表的创建结构 .schema student *
以 . 开头的点命令 ✅ 立即执行 sqlite> → (执行完回到 sqlite>)
SQL 语句以 ; 结尾 ✅ 立即执行 sqlite> → (执行完回到 sqlite>)
SQL 语句没有 ; ❌ 不执行,继续等待 sqlite> → ...> (进入续行模式)
多行 SQL 语句 ❌ 不执行,继续等待 sqlite> → ...> (直到输入 ;)
括号不匹配 ❌ 不执行,继续等待 sqlite> → ...> (直到括号闭合)
SQL语句:
支持的数据类型
NULL 表示空值。
INTEGER 有符号整数,根据值的大小,以 1、2、3、4、6 或 8 字节存储。
REAL 浮点数,以 8 字节的 IEEE 浮点数存储。
TEXT 文本字符串,使用数据库的编码(如 UTF-8)存储。
BLOB 二进制大对象,数据会按照输入时的原样进行存储。
1.create table语句
CREATE TABLE IF NOT EXISTS 表名 (
列名1 数据类型 约束,
列名2 数据类型 约束,
...
表级约束
);
IF NOT EXISTS:如果表已存在则不创建
表名和列名不区分大小写,但建议用大写关键字
CREATE TABLE IF NOT EXISTS student (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER DEFAULT 18,
score REAL,
class TEXT,
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
id:自增主键,唯一标识每条记录
name:不能为空
age:默认为18
score:浮点数,可以为空
class:文本,可以为空
create_time:自动记录创建时间
2.insert into
-- 完整写法(指定列名,推荐)
INSERT INTO 表名 (列1, 列2, 列3, ...) VALUES (值1, 值2, 值3, ...);
-- 简写(不指定列名,必须按顺序提供所有列的值)
INSERT INTO 表名 VALUES (值1, 值2, 值3, ...);
必须按照列要求给出一行完整数据,否则会报错
例子:
-- 推荐写法:明确指定列名
INSERT INTO student (name, age, score, class)
VALUES ('张三', 20, 95.5, '高三1班');
-- 一次插入多条数据(效率高)
INSERT INTO student (name, age, score, class) VALUES
('赵六', 21, 78.5, '高三1班'),
('孙七', 20, 88.0, '高三3班'),
('周八', 22, 93.5, '高三2班');
-- 插入默认值或NULL
INSERT INTO student (name, age, score, class)
VALUES ('小明', DEFAULT, NULL, DEFAULT);
3.select
生成一张新的表,可以对内容进行筛选,可以排序
select (列名1, 列名2, ...) from 表名;
查看表明的所有内容
select * from 表名;
显示列名,默认关 .header on
更改显示格式,.mode 模式名称 可选参数, 默认为 .mode list
.width 5 10 8 6 -- 分别设置每列宽度
.mode column 左对其
4.where子句
SELECT 列名 FROM 表名 WHERE 条件;
UPDATE 表名 SET 列 = 值 WHERE 条件;
DELETE FROM 表名 WHERE 条件;
模糊查询(LIKE)
% 匹配任意字符(0个或多个) '张%' = 以"张"开头
_ 匹配单个字符 '张_' = "张"后面跟1个字符
-- 查询姓"张"的学生(名字以"张"开头)
SELECT * FROM student WHERE name LIKE '张%';
-- 查询名字包含"三"的学生
SELECT * FROM student WHERE name LIKE '%三%';
-- 查询名字是"张三"或"张四"(两个字)
SELECT * FROM student WHERE name LIKE '张_';
-- 查询名字以"三"结尾的学生
SELECT * FROM student WHERE name LIKE '%三';
空值查询(NULL)
-- 查询 class 为 NULL 的学生(注意:不能用 = NULL)
SELECT * FROM student WHERE class IS NULL;
-- 查询 class 不为 NULL 的学生
SELECT * FROM student WHERE class IS NOT NULL;
-- 错误写法(不会报错,但查不到任何结果)
SELECT * FROM student WHERE class = NULL; -- ❌ 永远查不到
AND 且(所有条件都满足) WHERE age > 18 AND score >= 90
OR 或(任意条件满足) WHERE age < 18 OR age > 25
NOT 非(取反) WHERE NOT age = 20
-- 年龄大于18 且 分数大于90
SELECT * FROM student WHERE age > 18 AND score > 90;
-- 年龄小于18 或 年龄大于25
SELECT * FROM student WHERE age < 18 OR age > 25;
-- 不是高三1班的学生
SELECT * FROM student WHERE NOT class = '高三1班';
BETWEEN ... AND ...(包含边界)
-- 年龄在18到22之间(包含18和22)
SELECT * FROM student WHERE age BETWEEN 18 AND 22;
-- 等价于
SELECT * FROM student WHERE age >= 18 AND age <= 22;
IN(匹配多个值)
-- 查询指定班级的学生
SELECT * FROM student WHERE class IN ('高三1班', '高三2班', '高三3班');
-- 等价于
SELECT * FROM student WHERE class = '高三1班' OR class = '高三2班' OR class = '高三3班';
-- 查询分数为90, 95, 100的学生
SELECT * FROM student WHERE score IN (90, 95, 100);
NOT IN(排除多个值)
-- 查询不是高三1班和高三2班的学生
SELECT * FROM student WHERE class NOT IN ('高三1班', '高三2班');
ORDER BY 排序
-- 查询年龄大于18的学生,按分数从高到低排序
SELECT * FROM student
WHERE age > 18
ORDER BY score DESC;
-- 先按班级排序,再按分数排序
SELECT * FROM student
WHERE age > 18
ORDER BY class ASC, score DESC;
LIMIT 限制条数
-- 查询分数最高的3个学生
SELECT * FROM student
ORDER BY score DESC
LIMIT 3;
如果每一行有其固定的ID
-- 查询 id=2 的行
SELECT * FROM student WHERE id = 2; 或 score >= 90, name = '赵%'
-- 更新 id=2 的行
UPDATE student SET age = 23 WHERE id = 2;
-- 删除 id=2 的行
DELETE FROM student WHERE id = 2;
drop table
DROP TABLE IF EXISTS 表名;
IF EXISTS:如果表存在则删除,不存在也不报错
-- 删除 student 表(如果存在)
DROP TABLE IF EXISTS student;
-- 删除 student 表(如果不存在会报错)
DROP TABLE student;
多表联合查询
单引号 ' ' 包裹字符串和文本值 WHERE name = '张三'
双引号 " " 包裹标识符(表名、列名) SELECT "name" FROM "student"
当 id 设置为 INTEGER PRIMARY KEY AUTOINCREMENT 后,插入时系统会自动生成唯一 ID,你完全不用管它
joins
cross join;
SELECT * FROM 表1 CROSS JOIN 表2;
-- 创建颜色表
CREATE TABLE colors (color TEXT);
INSERT INTO colors VALUES ('红色'), ('蓝色'), ('绿色');
-- 创建尺寸表
CREATE TABLE sizes (size TEXT);
INSERT INTO sizes VALUES ('S'), ('M'), ('L');
-- CROSS JOIN 查询
SELECT * FROM colors CROSS JOIN sizes;
color size
红色 S
红色 M
红色 L
蓝色 S
蓝色 M
蓝色 L
绿色 S
绿色 M
绿色 L
-- 生成所有颜色×尺寸组合(电商SKU)
SELECT c.color, s.size, 'SKU_' || c.color || '_' || s.size AS sku_code
FROM colors c CROSS JOIN sizes s;
color size sku_code
红色 S SKU_红色_S
红色 M SKU_红色_M
红色 L SKU_红色_L
蓝色 S SKU_蓝色_S
...
查看时使用现有表信息的列来新建列名
select 表名.列名 as 新列名,...
innre join;
SELECT 列名列表
FROM 表1
INNER JOIN 表2 ON 表1.关联列 = 表2.关联列
INNER JOIN ...;
SELECT
student.name AS 学生,
course.course_name AS 课程,
score.score AS 分数,
course.teacher AS 老师
FROM student
INNER JOIN score ON student.id = score.student_id
INNER JOIN course ON score.subject = course.course_name;
outer join;
SELECT 列名列表
FROM 左表
LEFT JOIN 右表 ON 左表.关联列 = 右表.关联列;
左为主,将右表信息对齐左表
==============================================================================================
sqlite函数接口
sqlite3 *pdb; //pdb就是句柄
sqlite3_open;
int sqlite3_open(
const char *filename, /* 数据库文件名,UTF-8编码 */
sqlite3 **ppDb /* 输出参数:指向数据库连接句柄的指针 */
);
功能:
打开数据库文件,修改定义的sqlite3 *pdb的pdb为指向数据库的句柄指针
参数:
filename const char*
输入参数:数据库文件的路径(UTF-8编码)。
• 可以是绝对路径:"/home/user/data.db"
• 可以是相对路径:"mydb.db"
• 特殊值:":memory:"(内存数据库)
• 特殊值:""(临时磁盘数据库)
ppDb sqlite3**
输出参数:指向 sqlite3* 类型变量的指针。
• 函数执行成功后,会在这里填入一个有效的数据库连接句柄。
• 后续的 SQL 操作都通过这个句柄进行。
• 使用前必须先声明 sqlite3 *db;,然后传入 &db。
返回值:
成功返回0,
SQLITE_OK 0 0 成功:数据库打开成功,连接已建立。
SQLITE_ERROR 1 1 SQL错误或缺失数据库:通用错误。
SQLITE_INTERNAL 2 2 内部逻辑错误。
SQLITE_PERM 3 3 权限不足(无读写权限)。
SQLITE_ABORT 4 4 操作被中止。
SQLITE_BUSY 5 5 数据库被其他进程锁定。
SQLITE_LOCKED 6 6 数据库表被锁定。
SQLITE_NOMEM 7 7 内存分配失败。
SQLITE_READONLY 8 8 数据库文件只读,无法写入。
SQLITE_INTERRUPT 9 9 操作被中断。
SQLITE_IOERR 10 10 磁盘I/O错误:无法读取或写入文件。
SQLITE_CORRUPT 11 11 数据库文件损坏。
SQLITE_NOTFOUND 12 12 数据库文件不存在(但 sqlite3_open 会自动创建)。
SQLITE_FULL 13 13 磁盘空间已满。
SQLITE_CANTOPEN 14 14 无法打开文件:路径无效或权限不足。
SQLITE_PROTOCOL 15 15 锁定协议错误。
SQLITE_EMPTY 16 16 空文件。
SQLITE_SCHEMA 17 17 数据库schema已改变。
SQLITE_TOOBIG 18 18 数据太大(超过限制)。
SQLITE_CONSTRAINT 19 19 违反约束条件。
SQLITE_MISMATCH 20 20 数据类型不匹配。
SQLITE_MISUSE 21 21 API使用错误(如用 sqlite3_open 已打开的连接)。
SQLITE_NOLFS 22 22 不支持大文件系统。
SQLITE_AUTH 23 23 授权失败。
SQLITE_FORMAT 24 24 文件格式错误。
SQLITE_RANGE 25 25 参数超出范围。
SQLITE_NOTADB 26 26 不是数据库文件:文件头错误。
打印错误,fprintf(stderr, "%s\n", sqlite3_errmsg(pdb));
const char *sqlite3_errmsg(sqlite3 *db);
参数 db:数据库连接句柄(由 sqlite3_open 获得)
返回值 const char*:指向错误信息字符串的指针(UTF-8 编码)
目库存在,文件不存在会自动创建空白的.db文件
=============================================================================================
sqlite3_exec;
int sqlite3_exec(
sqlite3 *db, /* 数据库连接句柄 */
const char *sql, /* 要执行的 SQL 语句(可多条) */
int (*callback)(void *data, int argc, char **argv, char **col_name), // 回调函数(查询结果处理
void *data, /* 回调函数的第一个参数(用户数据) */
char **errmsg /* 错误信息输出(需要手动释放) */
);
功能: 执行一条SQL语句
参数:
db sqlite3* 数据库连接句柄 由sqlite3_open获得
sql const char* 要执行的 SQL 语句(可以包含多条语句,用 ; 分隔)
callback int (*)(void*, int, char**, char** ) 回调函数:处理 SELECT 查询结果的每一行,如果是 INSERT/UPDATE/DELETE 等非查询语句,传 NULL, 如果正常执行一定要return 0;
data void* 用户自定义数据,会原样传给回调函数的第一个参数
errmsg char** 输出参数:如果出错,返回错误信息字符串,使用完后必须调用 sqlite3_free(errmsg) 释放
返回值:
SQLITE_OK (0) 执行成功
其他错误码 执行失败(如 SQLITE_ERROR、SQLITE_CONSTRAINT 等)
void *arg 第一个参数,自定义传入参数
colnum 列数
pcontent 列的内容指针数组
ptitle 列的名称指针数组
该回调函数,会随着select每找到一个数据就会被调用一次
如果select没有找到,不会执行
int callbackfun(void *arg, int colnum, char **pcontent, char **ptitle)
{
return 0; //如果不返回0,会报错
}
void sqlite3_free(void *p);
参数 p:指向要释放的内存块的指针(由 SQLite API 返回)
返回值 无(void)
特性 如果传入 NULL,函数不做任何事(安全)
sqlite3_exec的最后一个参数是一个字符串的二级指针,如果出错,sqlite3_exec会将其对指向的一级指针的值更改为指向错误信息的指针,打印错误之后可以将其释放
例子
char *perrmsg = NULL;
int sqexecret = sqlite3_exec(pdb, cmd, NULL, NULL, &perrmsg);
if (sqexecret != SQLITE_OK)
{
fprintf(stderr, "sqlite_exec error %s\n", perrmsg);
sqlite3_free(perrmsg);
return -1;
}
================================================================================================
sqlite3_close
int sqlite3_close(sqlite3 *db);
功能 关闭一个 SQLite 数据库连接
参数 db:要关闭的数据库连接句柄(由 sqlite3_open 获得)
返回值 SQLITE_OK (0):成功关闭
SQLITE_BUSY (5):连接仍有未提交事务或未释放的语句