SQLite04-表数据管理

文章目录

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 中,不可用于 WHEREGROUP BYHAVING
  • DISTINCT 禁用:窗口函数前不可加 DISTINCT
(3)SQlite行转列
  • SQLite的行转列不支持直接的PIVOT语法
(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;
相关推荐
李宥小哥2 小时前
SQLite05-常用函数
java·开发语言·jvm
huohuopro2 小时前
idea配置servlet项目
java·servlet·intellij-idea
zzb15802 小时前
Agent学习-ReAct框架
java·人工智能·python·机器学习·ai
zhangx1234_2 小时前
java list介绍
java·开发语言·list
识君啊2 小时前
拆分与合并的艺术·分治思想:Java归并排序深度解析
java·数据结构·算法·排序算法·归并排序·分治
左左右右左右摇晃2 小时前
Java Object 类笔记
java·笔记
小箌2 小时前
JavaWeb & SpringBoot 总结
java·spring boot·后端
Smoothcloud_润云2 小时前
GORM 事务管理与 Repository 模式完整指南
前端·数据库·代码规范
aq55356002 小时前
SQL 注入漏洞原理以及修复方法
网络·数据库·sql