SQLite04-表数据管理
1、表数据管理
(1)通用增删改查
(2)SQLite插入数据
SQLite 主键为 INTEGER PRIMARY KEY 时,插入 NULL 可自动生成唯一值。
(3)SQLite数据删除
SQLite 不支持 TRUNCATE,可用 DELETE FROM 表名 。
(4)SQLite连接查询
类型
语法
是否支持
说明
内连接 (INNER JOIN)
JOIN / INNER JOIN
✅
返回匹配记录
左外连接 (LEFT JOIN)
LEFT JOIN
✅
左表全量 + 右表匹配
交叉连接 (CROSS JOIN)
CROSS JOIN
✅
笛卡尔积
右外连接 (RIGHT JOIN)
-
❌
需用 LEFT JOIN 模拟
全外连接 (FULL JOIN)
-
❌
需用 UNION 模拟
2、系统表查看
(1)常用系统表
sqlite_master:最重要的系统表,存储所有数据库对象的定义信息:表结构,索引,视图,触发器
sql
复制代码
-- 查询用户表
SELECT name FROM sqlite_master WHERE type = 'table';
-- 查询索引
SELECT name, tbl_name, sql FROM sqlite_master WHERE type = 'index';
-- 查询视图
SELECT name FROM sqlite_master WHERE type = 'view';
-- 查询建表语句
SELECT sql FROM sqlite_master WHERE type='table' AND name='users';
sqlite_temp_master:存储临时表信息
sql
复制代码
SELECT name FROM sqlite_temp_master;
(2)系统表特性
只读属性:不能直接INSERT/UPDATE/DELETE sqlite_master表
自动维护:使用CREATE/DROP命令自动更新
plsql
复制代码
-- 创建新表会自动在sqlite_master中添加记录
CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT);
-- 删除表会自动从sqlite_master中移除记录
DROP TABLE test;
隐藏性:
不能被重命名
不能被附加数据库访问(每个数据库有自己的sqlite_master)
不能在CREATE VIEW语句中引用
3、高级查询
(1)通用高级查询
(2)SQlite开窗函数
最低版本:SQLite 3.25.0(2018年9月)开始支持开窗函数,3.28.0 后完善了 GROUPS 和 RANGE 帧类型。低于此版本需升级。
调用位置限制:开窗函数只能出现在 SELECT 列表和顶层 ORDER BY 中,不可用于 WHERE、GROUP BY、HAVING。
DISTINCT 禁用:窗口函数前不可加 DISTINCT。
(3)SQlite行转列
(4)SQlite公共表表达式
递归CTE的深度:SQLite默认递归深度有限制,如果需要更深的递归,可以使用OPTION (MAXRECURSION n)(但SQLite的实现可能略有不同)
SQLite支持在一个WITH子句中定义多个CTE:
sql
复制代码
WITH
cte1 AS (SELECT * FROM table1 WHERE condition1),
cte2 AS (SELECT * FROM table2 WHERE condition2),
cte3 AS (SELECT * FROM cte1 JOIN cte2 ON cte1.id = cte2.id)
SELECT * FROM cte3;
(5)SQLite排除EXCEPT
大小写敏感:在SQLite中,EXCEPT操作符是大小写敏感的,列名的大小写必须匹配
不支持EXCEPT ALL:SQLite不支持EXCEPT ALL(保留重复行),只能返回唯一结果
3、事务和锁
(1)通用事务和锁
(2)SQLite的事务控制命令
sql
复制代码
BEGIN; -- 启动新事务
-- 执行数据库操作
COMMIT; -- 提交事务,永久保存修改
ROLLBACK; -- 回滚事务,撤销所有操作
(3)SQLite的事务隔离级别
SQLite通过MVCC(Multi-Version Concurrency Control)实现事务隔离,支持以下隔离级别:
串行化(Serializable):提供最高级别的隔离,确保事务按顺序执行。
可重复读(Repeatable Read):SQLite通过MVCC实现,保证同一事务内的多次读取数据一致。
注意:SQLite不支持读未提交(READ UNCOMMITTED)隔离级别,因为它可能导致脏读、不可重复读和幻读等问题。
MVCC机制与事务一致性:
事务读取数据时,SQLite返回事务ID小于或等于当前事务ID的数据版本
事务写入数据时,SQLite创建新页面并设置当前事务ID
保证同一事务内的多次读取结果一致
(4)SQLite的锁机制
SQLite使用基于磁盘文件的锁定机制,支持五种不同的锁定级别,从低到高依次为:
锁状态
描述
允许并发
适用场景
UNLOCKED
数据库默认状态,无任何事务访问
所有
事务开始前
SHARED
用于读取数据,多个事务可同时持有
是
读操作
RESERVED
事务表示写入意图,但未实际写入
读操作允许,写操作禁止
准备写入
PENDING
事务等待获取排他锁,等待所有共享锁释放
读操作已存在,新读操作禁止
写入前准备
EXCLUSIVE
事务正在写入数据库,唯一持有
无
实际写入操作
每个级别的锁都可以阻止更高级别的锁,但不能阻止更低级别的锁。例如,共享锁可以阻止其他事务获取排他锁,但不能阻止其他事务获取共享锁。
锁状态转换:锁状态转换遵循以下路径:
plain
复制代码
UNLOCKED → SHARED → RESERVED → PENDING → EXCLUSIVE → UNLOCKED
事务可以升级其锁定级别,但不能降级。例如,从共享锁可以升级到保留锁,但不能从保留锁降级到共享锁。
(5)SQLite的事务类型
DEFERRED事务(默认)
不获取任何锁(直到需要时)
开始于UNLOCKED状态
第一次读操作获取SHARED锁
第一次写操作获取RESERVED锁
sql
复制代码
BEGIN; -- 默认DEFERRED事务
IMMEDIATE事务
尝试获取RESERVED锁
保证没有其他连接可以写数据库
其他连接可以读取数据库
但会阻止其他IMMEDIATE或EXCLUSIVE事务
提交时可能返回SQLITE_BUSY错误(如果有读事务未完成)
sql
复制代码
BEGIN IMMEDIATE TRANSACTION;
EXCLUSIVE事务
尝试获取EXCLUSIVE锁
保证没有其他连接可以访问数据库
适合需要独占访问的场景
sql
复制代码
BEGIN EXCLUSIVE TRANSACTION;
(6)SQLite的锁机制工作流程
读操作流程
事务从UNLOCKED状态开始
执行读操作时获取SHARED锁
保持SHARED锁直到事务结束
写操作流程
事务从UNLOCKED状态开始
获取SHARED锁(如果需要读)
升级为RESERVED锁(表示写意图)
升级为PENDING锁(等待其他读锁释放)
最终获取EXCLUSIVE锁进行写入
提交后释放锁,回到UNLOCKED状态
(7)SQLite常见锁问题与解决方案
sql
复制代码
-- 连接A
BEGIN;
INSERT INTO foo VALUES('x');
-- 试图获取RESERVED锁
-- 连接B
BEGIN;
INSERT INTO foo VALUES('y');
-- 拥有PENDING锁
复制代码
- 原因:B先获取PENDING锁,阻止A获取RESERVED锁,导致A等待;同时A的共享锁阻止B获取EXCLUSIVE锁,形成死锁。
- 解决方案:
* 使用正确的事务类型:避免同时使用DEFERRED事务进行写操作
* 优先使用EXCLUSIVE事务进行写操作
* 确保写操作不会长时间持有锁
database is locked
现象:当尝试写入数据库而数据库已被其他事务锁定时,会返回"database is locked"错误。
解决方法:
确保写操作使用正确的事务类型(如EXCLUSIVE)
避免长时间持有事务
优化应用程序逻辑,减少事务持有时间
(8)实际应用建议
默认使用DEFERRED事务:适用于大多数读多写少的场景
写操作使用IMMEDIATE或EXCLUSIVE:确保写入操作能及时获取所需锁
避免长时间持有事务:减少锁竞争,提高并发性能
合理使用保存点:在复杂事务中设置保存点,提高事务灵活性
sql
复制代码
-- 使用保存点的示例
START TRANSACTION;
INSERT INTO accounts (id, balance) VALUES (1, 100);
SAVEPOINT sp1;
INSERT INTO accounts (id, balance) VALUES (2, 200);
ROLLBACK TO sp1; -- 仅回滚第二个操作
COMMIT;