SQLite 全面指南与常用操作
本文档为 SQLite 使用的详尽参考与实战指南,覆盖从基础概念、安装、命令行操作,到性能调优、并发与底层机制、备份恢复、扩展模块(FTS5/JSON1/R-Tree)、编程语言示例以及常见故障排查与实用脚本。适合开发者、运维与研究人员作为日常参考手册。
一. 快速开始(5 分钟上手)
1.1安装 SQLite CLI
Debian/Ubuntu:
sudo apt install sqlite3
。macOS:
brew install sqlite
。Windows: 下载
sqlite-tools
,使用sqlite3.exe
。
1.2创建数据库并执行简单命令
sqlite3 demo.db
sqlite> .headers on
sqlite> .mode column
sqlite> CREATE TABLE people(id INTEGER PRIMARY KEY, name TEXT, age INTEGER);
sqlite> INSERT INTO people (name, age) VALUES ('Alice', 30), ('Bob', 25);
sqlite> SELECT * FROM people;
sqlite> .exit
1.3 命令行工具使用(以 Windows 为例)
- 下载 SQLite 核心包:从 SQLite 官网 下载
sqlite-tools-win32-x86-xxxx.zip
; - 解压后得到
sqlite3.exe
,双击运行即可进入命令行交互模式; - 核心命令行指令:
.help:查看所有命令行帮助; .open <数据库名>:打开或创建数据库(如 .open test.db,若不存在则在当前目录创建 test.db 文件); .tables:查看当前数据库中所有表; .schema <表名>:查看指定表的创建语句; .exit 或 .quit:退出命令行模式。
二、数据库基础操作
SQLite 以单个文件存储整个数据库(如 test.db
),操作数据库的核心是 “打开 / 创建数据库” 和 “管理数据库元信息”。
2.1 创建 / 打开数据库
- 命令行方式:通过
.open
指令,如.open student.db
(若student.db
不存在则自动创建); - SQL 语句方式:无需显式 “创建数据库”,连接时指定不存在的文件名即自动创建;
- 注意:特殊数据库
:memory:
表示内存数据库,数据仅存于内存,程序退出后丢失,适合临时测试:.open :memory: -- 打开内存数据库
2.2 查看数据库信息
- 查看所有表:
.tables -- 命令行指令 SELECT name FROM sqlite_master WHERE type='table'; -- SQL 语句(通用)
-
查看表结构:
.schema student -- 命令行指令,查看 student 表结构 PRAGMA table_info(student); -- SQL 语句,查看表字段详情(含类型、主键等)
三、表操作(DDL:数据定义语言)
表是 SQLite 存储数据的核心载体,DDL 操作包括创建表、修改表、删除表,需遵循 SQLite 数据类型规则(SQLite 采用 “动态类型”,字段类型仅为建议,实际存储按值的类型决定)。
3.1 支持的数据类型
SQLite 常用数据类型(非严格约束,仅为 “类型提示”):
INTEGER
:整数(支持主键自增);TEXT
:字符串(UTF-8/UTF-16 编码);REAL
:浮点数(如 3.14、1.2e5);BLOB
:二进制数据(如图片、文件);NUMERIC
:数值类型(自动适配整数 / 浮点数 / 日期)。
3.2 创建表(CREATE TABLE)
基本语法
CREATE TABLE [IF NOT EXISTS] 表名 (字段1 类型 [约束1] [约束2],字段2 类型 [约束],...,[表级约束]
);
常用约束说明:
PRIMARY KEY
:主键(唯一标识记录,默认非空),若为INTEGER
类型,可加AUTOINCREMENT
实现自增;NOT NULL
:字段值不可为空;UNIQUE
:字段值唯一(允许多个 NULL);DEFAULT <值>
:默认值(如DEFAULT 0
、DEFAULT CURRENT_TIMESTAMP
);FOREIGN KEY (子表字段) REFERENCES 父表(父表主键)
:外键(维护表间关联,需开启外键支持)。
示例:创建学生表(含外键关联班级表)
1.先创建班级表(父表):
CREATE TABLE IF NOT EXISTS class (class_id INTEGER PRIMARY KEY AUTOINCREMENT, -- 班级ID(自增主键)class_name TEXT NOT NULL UNIQUE, -- 班级名称(唯一非空)create_time DEFAULT CURRENT_TIMESTAMP -- 创建时间(默认当前时间)
);
2.创建学生表(子表,关联班级表):
-- 开启外键支持(SQLite 默认关闭)
PRAGMA foreign_keys = ON;CREATE TABLE IF NOT EXISTS student (id INTEGER PRIMARY KEY AUTOINCREMENT, -- 学生ID(自增主键)name TEXT NOT NULL, -- 姓名(非空)age INTEGER CHECK (age > 0 AND age < 150), -- 年龄(范围约束)gender TEXT DEFAULT '未知', -- 性别(默认“未知”)class_id INTEGER, -- 关联班级ID-- 外键约束:student.class_id 关联 class.class_idFOREIGN KEY (class_id) REFERENCES class(class_id)ON DELETE SET NULL -- 若班级被删除,学生的 class_id 设为 NULLON UPDATE CASCADE -- 若班级ID更新,学生的 class_id 同步更新
);
3.3 修改表(ALTER TABLE)
SQLite 对 ALTER TABLE
支持有限,仅支持以下操作:
1.重命名表:
ALTER TABLE student RENAME TO new_student;
2.添加字段:
-- 给 student 表添加“电话”字段(允许为空,默认 NULL)
ALTER TABLE student ADD COLUMN phone TEXT;
3.重命名字段(SQLite 3.25.0+ 支持):
ALTER TABLE student RENAME COLUMN phone TO tel;
若需删除字段、修改字段类型 / 约束,需通过 “创建临时表 → 迁移数据 → 删除原表 → 重命名临时表” 实现,示例:
-- 1. 创建临时表(含修改后的结构)
CREATE TABLE student_temp AS SELECT id, name, age, gender, class_id FROM student;
-- 2. 删除原表
DROP TABLE student;
-- 3. 重命名临时表为原表名
ALTER TABLE student_temp RENAME TO student;
3.4 删除表(DROP TABLE)
-- 若表存在则删除(避免报错)
DROP TABLE IF EXISTS student;
四、数据操作(DML:数据操纵语言)
DML 用于增、删、改、查表中数据,是日常开发最频繁的操作。
4.1 插入数据(INSERT)
基本语法:
-- 1. 指定字段插入(推荐,字段顺序可自定义)
INSERT INTO 表名 (字段1, 字段2, ...) VALUES (值1, 值2, ...);-- 2. 不指定字段(需按表字段顺序插入所有值)
INSERT INTO 表名 VALUES (值1, 值2, ...);-- 3. 批量插入
INSERT INTO 表名 (字段1, 字段2, ...)
VALUES (值1-1, 值1-2, ...), (值2-1, 值2-2, ...), ...;
示例:
-- 1. 插入班级数据
INSERT INTO class (class_name) VALUES ('高一(1)班'), ('高一(2)班');-- 2. 插入学生数据(关联班级ID=1)
INSERT INTO student (name, age, gender, class_id)
VALUES ('张三', 16, '男', 1), ('李四', 15, '女', 2);-- 3. 插入默认值(gender 用默认值“未知”)
INSERT INTO student (name, age, class_id) VALUES ('王五', 16, 1);
4.2 更新数据(UPDATE)
基本语法:
UPDATE 表名SET 字段1=新值1, 字段2=新值2, ...[WHERE 条件] -- 若省略 WHERE,将更新表中所有记录(谨慎!)[LIMIT 数量]; -- 限制更新条数(避免误操作)
示例:
-- 1. 将“王五”的年龄改为17(指定 WHERE 条件,安全)
UPDATE student SET age = 17 WHERE name = '王五';-- 2. 将班级ID=1的学生性别改为“男”(批量更新,加 LIMIT 限制)
UPDATE student SET gender = '男' WHERE class_id = 1 LIMIT 10;
4.3 删除数据(DELETE)
基本语法:
DELETE FROM 表名[WHERE 条件] -- 省略则删除所有数据(谨慎!)[LIMIT 数量];
示例:
-- 1. 删除姓名为“李四”的学生
DELETE FROM student WHERE name = '李四';-- 2. 删除班级ID=2且年龄<16的学生(加条件过滤)
DELETE FROM student WHERE class_id = 2 AND age < 16;-- 3. 清空表(保留表结构,比 DROP TABLE 更安全)
DELETE FROM student;
4.4 查询数据(SELECT)
SELECT 是 SQL 中最灵活的操作,支持过滤、排序、分组、关联等复杂逻辑,基本语法:
SELECT [DISTINCT] 字段1, 字段2, ... -- DISTINCT 去重FROM 表名1[JOIN 表名2 ON 关联条件] -- 表关联(INNER/LEFT/RIGHT JOIN)[WHERE 行过滤条件][GROUP BY 分组字段] -- 按字段分组[HAVING 分组过滤条件] -- 过滤分组结果(需配合 GROUP BY)[ORDER BY 排序字段 [ASC/DESC]] -- 排序(ASC升序,DESC降序,默认ASC)[LIMIT 偏移量, 条数]; -- 分页(偏移量可选,如 LIMIT 10 取前10条,LIMIT 5,10 取第6-15条)
常用查询场景示例:
1.基础查询:查询学生表所有字段:
SELECT * FROM student; -- * 表示所有字段(生产环境建议指定具体字段,避免冗余)
2.条件过滤:查询班级 ID=1 且年龄≥16 的学生姓名和年龄:
SELECT name, age FROM student WHERE class_id = 1 AND age >= 16;
3.去重查询:查询所有学生的性别(去重):
SELECT DISTINCT gender FROM student;
4.排序查询:查询高一 (1) 班学生,按年龄降序排列:
SELECT name, age FROM studentWHERE class_id = (SELECT class_id FROM class WHERE class_name = '高一(1)班')ORDER BY age DESC;
5.表关联查询:查询学生姓名及所属班级名称(INNER JOIN 取两表匹配数据):
SELECT s.name AS 学生姓名, c.class_name AS 班级名称FROM student s -- s 是 student 表的别名INNER JOIN class c -- c 是 class 表的别名ON s.class_id = c.class_id; -- 关联条件:学生的班级ID=班级的ID
6.分组统计:按班级分组,统计每个班级的学生人数:
SELECT c.class_name AS 班级, COUNT(s.id) AS 学生人数FROM class cLEFT JOIN student s ON c.class_id = s.class_id -- LEFT JOIN 保留无学生的班级GROUP BY c.class_id -- 按班级ID分组(确保分组唯一)HAVING COUNT(s.id) >= 1; -- 过滤出学生数≥1的班级
7.分页查询:查询学生表第 2 页数据(每页 2 条):
-- 偏移量 = (页码-1)*每页条数 = (2-1)*2 = 2,取 2 条SELECT * FROM student LIMIT 2, 2;
五、高级操作
5.1 索引(INDEX)
索引用于加速查询,尤其当表数据量大时(如万级以上),但会增加插入 / 更新 / 删除的开销(需维护索引)。
1. 创建索引
-- 基本语法:给 student 表的 name 字段创建索引
CREATE [UNIQUE] INDEX [IF NOT EXISTS] 索引名 ON 表名(字段1, 字段2, ...);-- 示例1:给学生姓名创建普通索引(加速按姓名查询)
CREATE INDEX idx_student_name ON student(name);-- 示例2:给班级ID+年龄创建联合索引(加速“按班级+年龄”的组合查询)
CREATE INDEX idx_student_class_age ON student(class_id, age);-- 示例3:给班级名称创建唯一索引(确保班级名称唯一,与表约束 UNIQUE 功能类似)
CREATE UNIQUE INDEX idx_class_name ON class(class_name);
2. 删除索引
DROP INDEX IF EXISTS idx_student_name;
3. 查看索引
-- 查看所有索引
SELECT name FROM sqlite_master WHERE type='index';-- 查看指定表的索引
PRAGMA index_list(student);
5.2 事务(TRANSACTION)
SQLite 支持事务,确保一组操作 “要么全部成功,要么全部失败”,避免数据不一致。事务具有 ACID 特性(原子性、一致性、隔离性、持久性)。
基本语法:
BEGIN TRANSACTION; -- 开始事务(可简写为 BEGIN)-- 执行一系列 DML 操作(如 INSERT/UPDATE/DELETE)COMMIT; -- 提交事务(所有操作生效)-- 或ROLLBACK; -- 回滚事务(取消所有操作,恢复到事务开始前状态)
示例:转账场景(确保扣款和收款同时成功)
BEGIN;-- 1. A 账户扣款 100UPDATE account SET balance = balance - 100 WHERE user = 'A';-- 2. B 账户收款 100UPDATE account SET balance = balance + 100 WHERE user = 'B';-- 若两步均无错误,提交事务;若有错误(如 B 账户不存在),执行 ROLLBACKCOMMIT;-- ROLLBACK;
5.3 视图(VIEW)
视图是虚拟表,基于查询结果创建,不存储实际数据,仅保存查询逻辑,用于简化复杂查询、控制数据访问权限。
1. 创建视图
CREATE [OR REPLACE] VIEW 视图名 AS 查询语句;-- 示例:创建“学生班级视图”,简化关联查询CREATE OR REPLACE VIEW v_student_class ASSELECT s.id, s.name, s.age, c.class_nameFROM student sLEFT JOIN class c ON s.class_id = c.class_id;
2. 使用视图
-- 像查询普通表一样查询视图SELECT * FROM v_student_class WHERE class_name = '高一(1)班';
3. 删除视图
DROP VIEW IF EXISTS v_student_class;
5.4 触发器(TRIGGER)
触发器是自动执行的程序,当表发生特定操作(INSERT/UPDATE/DELETE)时,触发预设的 SQL 逻辑,用于数据校验、日志记录等场景。
基本语法:
CREATE [TRIGGER IF NOT EXISTS] 触发器名
[BEFORE/AFTER/INSTEAD OF] 操作类型(INSERT/UPDATE/DELETE)
ON 表名
[FOR EACH ROW] -- 行级触发器(每操作一行触发一次)
BEGIN-- 触发执行的 SQL 逻辑
END;
示例:记录学生表的更新日志
1.先创建日志表:
CREATE TABLE student_log (log_id INTEGER PRIMARY KEY AUTOINCREMENT,student_id INTEGER, -- 被操作的学生IDold_age INTEGER, -- 更新前的年龄new_age INTEGER, -- 更新后的年龄operate_time DEFAULT CURRENT_TIMESTAMP);
2.创建触发器:当学生表的年龄被更新时,自动插入日志:
CREATE TRIGGER trg_student_update_ageAFTER UPDATE ON student -- 学生表更新后触发FOR EACH ROW -- 每更新一行触发一次WHEN OLD.age != NEW.age -- 仅当年龄发生变化时触发BEGININSERT INTO student_log (student_id, old_age, new_age)VALUES (OLD.id, OLD.age, NEW.age); -- OLD 表示更新前的记录,NEW 表示更新后的记录END;
3.测试触发器:
-- 更新学生年龄,触发器会自动插入日志UPDATE student SET age = 18 WHERE name = '张三';-- 查看日志SELECT * FROM student_log;
4.删除触发器:
DROP TRIGGER IF EXISTS trg_student_update_age;
六、常用函数
SQLite 提供丰富的内置函数,简化数据处理:
函数类别 | 函数名 | 功能示例 |
---|---|---|
字符串 | LENGTH(str) | LENGTH(name) :获取姓名长度 |
UPPER(str) | UPPER(name) :姓名转大写 | |
数值 | COUNT(col) | COUNT(id) :统计非空记录数 |
SUM(col) | SUM(age) :计算年龄总和 | |
AVG(col) | AVG(age) :计算平均年龄 | |
日期 | DATE() | DATE() :获取当前日期(如 '2024-05-20') |
DATETIME() | DATETIME() :获取当前日期时间 | |
条件 | CASE WHEN | CASE WHEN age>=18 THEN '成年' ELSE '未成年' END |
七、注意事项
- 外键支持:SQLite 默认关闭外键约束,需通过
PRAGMA foreign_keys = ON;
开启(每次连接需重新执行,或在工具中配置默认开启); - 主键自增:仅
INTEGER
类型主键支持AUTOINCREMENT
,且需确保字段是主键; - 数据类型灵活性:SQLite 是 “动态类型”,字段类型仅为建议,如
TEXT
字段可存储整数,但建议遵循字段类型设计,避免混乱; - 性能优化:
- 大表查询需创建合适索引;
- 批量操作(如批量插入)建议用事务包裹,减少磁盘 IO;
- 避免使用
SELECT *
,仅查询需要的字段;
- 备份与恢复:SQLite 数据库是单个文件,直接复制
.db
文件即可备份;恢复时替换原文件即可。