SQLite数据库入门指南

目录

1 SQLite数据库介绍

2 SQLite的主要特点

2.1 轻量级

2.2 自包含

2.3 零配置

2.4 事务性(ACID兼容)

2.5 跨平台兼容性

2.6 无服务器架构

2.7 可靠性和稳定性

2.8 类型灵活性

2.9 支持标准SQL

2.10 广泛的编程语言支持

2.11 并发访问支持

3 SQLite常用SQL语句

3.1 创建表 (CREATE TABLE)

3.2 插入数据 (INSERT)

单行插入

多行插入

从其他表插入

3.3 查询数据 (SELECT)

基本查询

排序和限制

聚合函数

连接查询

3.4 更新数据 (UPDATE)

3.5 删除数据 (DELETE)

3.6 索引操作

3.7 事务管理

3.8 表结构修改 (ALTER TABLE)

3.9 视图操作

4 SQLite高级功能

4.1 事务与并发控制

WAL(Write-Ahead Logging)模式

4.2 触发器(Triggers)

触发器类型

4.3 视图(Views)与索引视图

基本视图

物化视图模拟

4.4 公共表表达式(CTE)与递归查询

基本CTE

递归CTE

4.5 窗口函数(Window Functions)

4.6 JSON支持

4.7 加密和安全

5 基本使用


1 SQLite数据库介绍

SQLite是一个轻量级的、自包含的、零配置的、事务性的SQL数据库引擎。它是世界上使用最广泛、的数据库引擎之一,被内置在所有手机和大多数计算机中,并且包含在无数应用程序中。

2 SQLite的主要特点

轻量级 - 整个数据库只是一个单一的文件,可以轻松地在设备间移动。自包含 - 不需要安装额外的、服务器软件或配置。零配置 - 不需要复杂的设置或管理。事务性 - 所有操作都是原子性、一致性、隔离性和持久性的(ACID)。跨平台 - 可在Windows、Linux、Mac OS X、Android、iOS等平台上运行。

2.1 轻量级

SQLite是一个极其轻量级的数据库系统,其核心库的大小通常只有几百KB到几MB。这使其成为资源受限设备的理想选择。

  • 整个数据库存储在单一文件中,默认扩展名为.db.sqlite

  • 没有单独的数据库服务器进程,直接嵌入到应用程序中

  • 平均安装大小约600KB,可以进一步优化至不到400KB

  • 内存占用极小,可以配置为仅使用几百KB的RAM

2.2 自包含

SQLite被设计为完全自包含的系统,这意味着它不依赖于任何外部组件。

  • 不需要外部依赖库

  • 没有外部配置文件

  • 不需要安装过程,可以直接使用

  • 跨平台兼容,代码可以直接在不同操作系统间移植

  • 所有数据库内容存储在单一文件中,便于备份和传输

2.3 零配置

与其他数据库系统不同,SQLite无需复杂的设置或配置过程。

  • 不需要安装和配置数据库服务器

  • 无需设置用户账号、权限或初始配置

  • 不需要数据库管理员(DBA)支持

  • 自动处理锁定和并发访问

  • 数据库文件可以放置在任何位置,无需特殊目录结构

2.4 事务性(ACID兼容)

尽管轻量,SQLite完全支持ACID(原子性、一致性、隔离性、持久性)特性:

  • 原子性(Atomicity) - 事务中的所有操作要么全部完成,要么全部不完成

BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT; -- 或者 ROLLBACK 如果出错
  • 一致性(Consistency) - 事务结束后,数据库从一个一致状态过渡到另一个一致状态

    • 强制执行约束和触发器

    • 维护外键完整性(当启用时)

  • 隔离性(Isolation) - 提供不同级别的隔离,防止并发事务干扰

    • 支持五种事务隔离级别:

      1. DEFERRED (默认)

      2. IMMEDIATE

      3. EXCLUSIVE

      4. READ UNCOMMITTED (使用PRAGMA read_uncommitted=1)

      5. SERIALIZABLE

  • 持久性(Durability) - 一旦事务提交,其变更将永久保存

    • 写入操作直接刷新到磁盘

    • 支持WAL(Write-Ahead Logging)模式,提高写入性能同时保障数据安全

2.5 跨平台兼容性

SQLite可在几乎所有主流计算平台上无缝运行:

  • Windows、macOS、Linux、Unix

  • Android、iOS、Windows Phone

  • 嵌入式系统

  • 每个平台上的数据库文件格式完全相同

  • 可以在32位和64位系统间自由移动数据库文件

  • 支持不同字节序的硬件架构(大端序和小端序)

2.6 无服务器架构

SQLite采用无服务器架构,与客户端-服务器模型的数据库系统不同:

  • 程序直接读写数据库文件,无需通过服务器

  • 没有网络层或IPC(进程间通信)开销

  • 减少了系统复杂性和潜在故障点

  • 适合嵌入式应用和单用户应用程序

  • 简化了部署和维护

# SQLite直接访问示例
import sqlite3
conn = sqlite3.connect('database.db')  # 直接连接到文件

2.7 可靠性和稳定性

SQLite经过严格测试,以确保高度可靠:

  • 超过100%的测试覆盖率(某些代码路径有多个测试)

  • 包含数千个测试用例,测试总数超过数百万

  • 采用模糊测试和边界条件测试

  • 实现了故障注入测试,模拟各种错误情况

  • 设计遵循"宁可拒绝错误的操作,也不破坏数据库"原则

  • 广泛的实际应用验证,数十亿设备上运行

2.8 类型灵活性

SQLite采用动态类型系统,更加灵活:

  • 采用"亲和类型"系统而非严格类型

  • 五种主要存储类:NULL、INTEGER、REAL、TEXT和BLOB

  • 可以将任何类型的数据存储在任何列中(除了有约束的列)

  • 自动类型转换,例如将文本"123"存储在INTEGER列时会转换为数字123

  • 使用CAST函数可以进行显式类型转换

2.9 支持标准SQL

SQLite实现了SQL标准的大部分功能:

  • 支持大部分SQL-92标准

  • 支持复杂查询、子查询、联接、视图和触发器

  • 支持事务和索引

  • 支持公共表表达式(CTE)和窗口函数(SQLite 3.25+)

  • 支持JSON函数(SQLite 3.9+)

-- 复杂查询示例
WITH ranked_employees AS (
  SELECT 
    name, 
    department,
    salary,
    RANK() OVER (PARTITION BY department ORDER BY salary DESC) as salary_rank
  FROM employees
)
SELECT name, department, salary
FROM ranked_employees
WHERE salary_rank <= 3;

2.10 广泛的编程语言支持

几乎所有主流编程语言都有SQLite绑定:

  • C/C++(原生库)

  • Python(sqlite3内置模块)

  • Java(JDBC驱动)

  • C#/.NET

  • JavaScript/Node.js

  • PHP、Ruby、Go、Rust等

2.11 并发访问支持

尽管SQLite主要设计用于单用户场景,但它也支持有限的并发:

  • 多个读取操作可以同时进行

  • 写操作会阻塞其他写操作,但不阻塞读操作(在WAL模式下)

  • 支持锁升级机制:共享锁→保留锁→独占锁

  • WAL(Write-Ahead Logging)模式提供更好的并发性能 

3 SQLite常用SQL语句

3.1 创建表 (CREATE TABLE)

CREATE TABLE employees (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    department TEXT,
    salary REAL DEFAULT 0.0,
    hire_date TEXT,
    is_active INTEGER DEFAULT 1
);

注意事项:

  • PRIMARY KEY 定义主键,AUTOINCREMENT 使ID值自动递增

  • NOT NULL 限制列不能为空

  • DEFAULT 为列指定默认值

  • SQLite中没有严格的布尔类型,通常使用INTEGER(0/1)表示

  • 日期时间通常以TEXT或INTEGER(UNIX时间戳)存储

  • 一旦创建表,修改表结构比较有限,应提前规划好表设计

3.2 插入数据 (INSERT)

单行插入

INSERT INTO employees (name, department, salary, hire_date)
VALUES ('张三', '技术部', 10000.00, '2025-01-15');

多行插入

INSERT INTO employees (name, department, salary, hire_date) VALUES
    ('李一', '市场部', 8500.00, '2024-02-20'),
    ('王二', '财务部', 9000.00, '2024-03-10'),
    ('赵三', '技术部', 11000.00, '2024-01-05');

从其他表插入

INSERT INTO active_employees (id, name, department)
SELECT id, name, department FROM employees WHERE is_active = 1;

注意事项:

  • 避免硬编码值,应使用参数化查询防止SQL注入

  • 不必为自增字段提供值,可以省略或使用NULL

  • 如果不指定列名,必须按表定义的确切顺序提供所有列的值

  • 大批量插入时应使用事务来提高性能

3.3 查询数据 (SELECT)

基本查询

-- 查询所有列
SELECT * FROM employees;
​
-- 查询特定列
SELECT id, name, department FROM employees;
​
-- 条件查询
SELECT * FROM employees WHERE department = '技术部';
​
-- 多条件查询
SELECT * FROM employees 
WHERE department = '技术部' AND salary > 9000;

排序和限制

-- 排序
SELECT * FROM employees ORDER BY salary DESC;
​
-- 多字段排序
SELECT * FROM employees ORDER BY department ASC, salary DESC;
​
-- 限制结果数量
SELECT * FROM employees LIMIT 10;
​
-- 分页查询
SELECT * FROM employees LIMIT 10 OFFSET 20; -- 第3页(每页10条)

聚合函数

-- 计数
SELECT COUNT(*) FROM employees;
​
-- 分组统计
SELECT department, COUNT(*) as employee_count, AVG(salary) as avg_salary
FROM employees
GROUP BY department
HAVING COUNT(*) > 2;

连接查询

-- 内连接
SELECT e.name, d.department_name
FROM employees e
JOIN departments d ON e.department = d.id;
​
-- 左连接
SELECT e.name, d.department_name
FROM employees e
LEFT JOIN departments d ON e.department = d.id;

注意事项:

  • 避免使用 SELECT * 在生产环境,只查询需要的列

  • 使用 LIMIT 控制返回结果数量,避免返回过多数据

  • GROUP BY 子句中应包含SELECT中所有非聚合字段

  • 连接查询时使用表别名提高可读性

  • 复杂查询考虑使用子查询或CTE(公共表表达式)提高可读性

  • 大表查询应考虑添加索引以提高性能

3.4 更新数据 (UPDATE)

-- 基本更新
UPDATE employees 
SET salary = 12000 
WHERE name = '张三';
​
-- 多字段更新
UPDATE employees 
SET salary = salary * 1.1, 
    department = '研发部' 
WHERE department = '技术部';
​
-- 使用子查询更新
UPDATE employees
SET salary = (SELECT AVG(salary) FROM employees)
WHERE id = 1;

注意事项:

  • 必须使用 WHERE 子句,否则会更新所有行

  • 在大规模更新前先使用 SELECT 测试条件是否正确

  • 更新操作放在事务中,避免部分更新导致数据不一致

  • 不要在一个语句中多次更新同一列

  • 更新引用的表数据时注意外键约束

3.5 删除数据 (DELETE)

-- 基本删除
DELETE FROM employees WHERE id = 3;
​
-- 条件删除
DELETE FROM employees WHERE hire_date < '2023-01-01';
​
-- 使用子查询删除
DELETE FROM employees 
WHERE department IN (SELECT id FROM departments WHERE is_active = 0);
​
-- 清空表数据
DELETE FROM employees; -- 删除所有行但保留表结构

注意事项:

  • 总是使用 WHERE 条件,否则会删除所有数据

  • 删除前先使用SELECT验证WHERE条件

  • 永久性操作无法恢复,应在事务中执行以便需要时回滚

  • 对于大量数据删除,可能会导致数据库文件碎片,考虑定期使用VACUUM

  • 如果只是想清空表,DELETE FROM DROP TABLE + CREATE TABLE 慢3.

3.6 索引操作

-- 创建索引
CREATE INDEX idx_employees_department ON employees(department);
​
-- 创建唯一索引
CREATE UNIQUE INDEX idx_employees_email ON employees(email);
​
-- 创建复合索引
CREATE INDEX idx_employees_dept_salary ON employees(department, salary);
​
-- 删除索引
DROP INDEX idx_employees_department;

注意事项:

  • 索引加速查询但会减慢写入操作

  • 不要过度建立索引,只为经常作为查询条件的列创建索引

  • 考虑列的基数(唯一值数量),低基数列(如性别)索引效果有限

  • 复合索引的列顺序很重要,最常用于等值查询的列应放在前面

  • 索引占用额外存储空间

3.7 事务管理

-- 开始事务
BEGIN TRANSACTION;
​
-- 执行多条SQL语句
INSERT INTO departments (name) VALUES ('新部门');
UPDATE employees SET department = last_insert_rowid() WHERE id IN (1, 2, 3);
​
-- 提交事务
COMMIT;
​
-- 或回滚事务
-- ROLLBACK;

注意事项:

  • 事务保证所有操作要么全部成功,要么全部失败

  • 长事务会锁定资源,影响并发性能

  • SQLite默认每条语句自动开启事务(自动提交模式)

  • 批量操作应放在显式事务中以提高性能

  • 事务隔离级别可以通过PRAGMA语句调整

3.8 表结构修改 (ALTER TABLE)

-- 重命名表
ALTER TABLE employees RENAME TO staff;
​
-- 添加列
ALTER TABLE employees ADD COLUMN email TEXT;
​
-- 重命名列 (SQLite 3.25+)
ALTER TABLE employees RENAME COLUMN name TO full_name;
​
-- 删除列 (SQLite 3.35+)
ALTER TABLE employees DROP COLUMN notes;

注意事项:

  • SQLite的ALTER TABLE功能有限,无法修改列类型或约束

  • 复杂的表结构修改通常需要创建新表、复制数据、删除旧表、重命名新表

  • 添加列时如有NOT NULL约束,必须提供默认值

  • 表结构修改是重写整个表的操作,对大表可能很耗时

3.9 视图操作

-- 创建视图
CREATE VIEW active_employees AS
SELECT id, name, department, salary
FROM employees
WHERE is_active = 1;
​
-- 使用视图
SELECT * FROM active_employees WHERE salary > 10000;
​
-- 删除视图
DROP VIEW active_employees;

注意事项:

  • 图是虚拟表,不存储实际数据

  • 视图简化复杂查询,提供数据抽象层

  • SQLite视图是只读的,不支持更新操作

  • 视图会降低查询性能,实际是在查询时执行定义的SELECT语句

4 SQLite高级功能

4.1 事务与并发控制

SQLite提供了完整的事务处理功能,支持ACID属性,这在轻量级数据库中相当罕见。

-- 1. 延迟事务(默认)
BEGIN DEFERRED TRANSACTION;
​
-- 2. 立即事务(获取RESERVED锁)
BEGIN IMMEDIATE TRANSACTION;
​
-- 3. 排他事务(获取EXCLUSIVE锁)
BEGIN EXCLUSIVE TRANSACTION;

其他两种隔离级别通过PRAGMA设置:

-- 4. 读未提交
PRAGMA read_uncommitted = 1;
​
-- 5. 可串行化(默认行为)
PRAGMA read_uncommitted = 0;

WAL(Write-Ahead Logging)模式

WAL模式显著提高了并发性能,允许读和写同时进行:

-- 启用WAL模式
PRAGMA journal_mode = WAL;
​
-- 检查当前模式
PRAGMA journal_mode;
​
-- 设置检查点阈值(页数)
PRAGMA wal_autocheckpoint = 1000;

注意事项:

  • WAL模式会创建额外的文件(-wal和-shm)

  • 适合读多写少的应用

  • 提高了崩溃恢复的可靠性

  • 在需要提高并发性能时优先考虑

4.2 触发器(Triggers)

触发器是在特定数据库事件发生时自动执行的SQL代码块。

触发器类型

-- 1. BEFORE INSERT触发器
CREATE TRIGGER validate_email_before_insert
BEFORE INSERT ON users
FOR EACH ROW
WHEN NEW.email NOT LIKE '%@%.%'
BEGIN
    SELECT RAISE(ABORT, '无效的电子邮件格式');
END;
​
-- 2. AFTER UPDATE触发器
CREATE TRIGGER update_last_modified
AFTER UPDATE ON documents
FOR EACH ROW
BEGIN
    UPDATE documents SET last_modified = CURRENT_TIMESTAMP
    WHERE id = NEW.id;
END;
​
-- 3. INSTEAD OF触发器(用于视图)
CREATE TRIGGER instead_of_insert_on_active_users
INSTEAD OF INSERT ON active_users_view
FOR EACH ROW
BEGIN
    INSERT INTO users (name, email, is_active)
    VALUES (NEW.name, NEW.email, 1);
END;

高级应用:审计日志

-- 创建审计日志表
CREATE TABLE audit_log (
    id INTEGER PRIMARY KEY,
    table_name TEXT,
    operation TEXT,
    timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
    old_values TEXT,
    new_values TEXT,
    user_id INTEGER
);
​
-- 创建审计触发器
CREATE TRIGGER audit_users_update
AFTER UPDATE ON users
FOR EACH ROW
BEGIN
    INSERT INTO audit_log (table_name, operation, old_values, new_values, user_id)
    VALUES ('users', 'UPDATE', 
            json_object('id', OLD.id, 'name', OLD.name, 'email', OLD.email),
            json_object('id', NEW.id, 'name', NEW.name, 'email', NEW.email),
            (SELECT value FROM app_context WHERE key = 'current_user_id'));
END;

注意事项:

  • 触发器会影响性能,尤其是大量数据操作时

  • 复杂触发器可能导致调试困难

  • 触发器之间可能有依赖关系,设计时需谨慎考虑执行顺序

  • 递归触发器可能导致无限循环

4.3 视图(Views)与索引视图

视图提供了一个强大的抽象层,能简化复杂查询。

基本视图

-- 简单视图
CREATE VIEW active_employees AS
SELECT * FROM employees WHERE status = 'active';
​
-- 复杂联接视图
CREATE VIEW employee_details AS
SELECT e.id, e.name, d.name AS department_name, 
       p.title AS position, e.salary, e.hire_date
FROM employees e
JOIN departments d ON e.department_id = d.id
JOIN positions p ON e.position_id = p.id;

物化视图模拟

SQLite不直接支持物化视图,但可以通过触发器模拟:

-- 创建物化表
CREATE TABLE mat_department_stats (
    department_id INTEGER PRIMARY KEY,
    department_name TEXT,
    employee_count INTEGER,
    avg_salary REAL,
    last_updated TEXT DEFAULT CURRENT_TIMESTAMP
);
​
-- 初始填充
INSERT INTO mat_department_stats (department_id, department_name, employee_count, avg_salary)
SELECT d.id, d.name, COUNT(e.id), AVG(e.salary)
FROM departments d
LEFT JOIN employees e ON d.id = e.department_id
GROUP BY d.id, d.name;
​
-- 创建刷新触发器
CREATE TRIGGER refresh_dept_stats_after_employee_change
AFTER INSERT OR UPDATE OR DELETE ON employees
FOR EACH ROW
BEGIN
    -- 删除受影响部门的统计
    DELETE FROM mat_department_stats 
    WHERE department_id IN (OLD.department_id, NEW.department_id);
    
    -- 重新计算受影响部门的统计
    INSERT INTO mat_department_stats (department_id, department_name, employee_count, avg_salary)
    SELECT d.id, d.name, COUNT(e.id), AVG(e.salary)
    FROM departments d
    LEFT JOIN employees e ON d.id = e.department_id
    WHERE d.id IN (OLD.department_id, NEW.department_id)
    GROUP BY d.id, d.name;
END;

注意事项:

  • 视图中最好不要使用SELECT *,应明确列出需要的列

  • 复杂视图会影响性能,尤其是多层嵌套视图

  • 考虑在经常查询的视图上建立索引来提高性能

4.4 公共表表达式(CTE)与递归查询

CTE提供了临时结果集,可以在一个查询中多次引用,极大提高复杂查询的可读性。

基本CTE

-- 基本CTE示例
WITH high_salary_employees AS (
    SELECT id, name, salary
    FROM employees
    WHERE salary > 10000
),
department_counts AS (
    SELECT department_id, COUNT(*) as emp_count
    FROM employees
    GROUP BY department_id
)
SELECT e.*, dc.emp_count
FROM high_salary_employees e
JOIN employees full ON e.id = full.id
JOIN department_counts dc ON full.department_id = dc.department_id;

递归CTE

递归CTE非常强大,可以处理层级数据和图形结构:

-- 组织结构层级查询
WITH RECURSIVE org_hierarchy AS (
    -- 基础查询:找到所有顶级管理者
    SELECT id, name, manager_id, 0 AS level, name AS path
    FROM employees
    WHERE manager_id IS NULL
    
    UNION ALL
    
    -- 递归部分:找到所有下级
    SELECT e.id, e.name, e.manager_id, oh.level + 1, 
           oh.path || ' > ' || e.name
    FROM employees e
    JOIN org_hierarchy oh ON e.manager_id = oh.id
)
SELECT * FROM org_hierarchy ORDER BY path;
-- 任务依赖关系和关键路径查询
WITH RECURSIVE task_dependencies AS (
    SELECT id, name, prerequisite_id, duration, 
           duration AS earliest_start,
           duration AS latest_finish
    FROM tasks
    WHERE prerequisite_id IS NULL
    
    UNION ALL
    
    SELECT t.id, t.name, t.prerequisite_id, t.duration, 
           td.earliest_start + t.duration,
           td.latest_finish + t.duration
    FROM tasks t
    JOIN task_dependencies td ON t.prerequisite_id = td.id
)
SELECT * FROM task_dependencies
ORDER BY latest_finish DESC;

注意事项:

  • 递归CTE必须有一个非递归部分和一个递归部分,用UNION或UNION ALL连接

  • 递归查询可能导致无限循环,SQLite默认限制1000次迭代,可通过PRAGMA recursive_triggers调整

  • 复杂递归查询性能可能较差,应考虑适当索引和查询优化

4.5 窗口函数(Window Functions)

窗口函数允许在不改变结果集行数的情况下进行计算,非常适合数据分析。

-- 基本窗口函数
SELECT name, department_id, salary,
       RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) as dept_salary_rank,
       AVG(salary) OVER (PARTITION BY department_id) as dept_avg_salary,
       salary - AVG(salary) OVER (PARTITION BY department_id) as diff_from_avg,
       SUM(salary) OVER (PARTITION BY department_id) as dept_total_salary,
       salary / SUM(salary) OVER (PARTITION BY department_id) as pct_of_dept_salary
FROM employees;
​
-- 移动平均与累计求和
SELECT date, sales,
       AVG(sales) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) as moving_avg_7day,
       SUM(sales) OVER (ORDER BY date) as cumulative_sales
FROM daily_sales;
​
-- 滑动窗口比较
SELECT date, sales,
       sales - LAG(sales) OVER (ORDER BY date) as daily_change,
       sales - LAG(sales, 7) OVER (ORDER BY date) as weekly_change,
       LEAD(sales) OVER (ORDER BY date) as next_day_sales
FROM daily_sales;

注意事项:

  • 窗口函数仅支持SQLite 3.25+(2018年后版本)

  • 窗口函数是在结果集上操作,而非物理表

  • 复杂窗口函数可能占用大量内存,注意数据集大小

  • 窗口函数与GROUP BY不同:GROUP BY会减少行数,窗口函数保持原有行

4.6 JSON支持

从SQLite 3.9开始,提供了内置JSON函数,可以方便地处理JSON数据。

-- 存储JSON数据
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT,
    preferences JSON
);
​
INSERT INTO users (name, preferences) VALUES (
    '张三', 
    '{"theme":"dark","notifications":true,"language":"zh-CN"}'
);
​
-- 提取JSON值
SELECT name, 
       json_extract(preferences, '$.theme') as theme,
       json_extract(preferences, '$.language') as language
FROM users;
​
-- 使用简写语法(->)
SELECT name, 
       preferences->'$.theme' as theme,
       preferences->'$.language' as language
FROM users;
​
-- 更新JSON数据
UPDATE users
SET preferences = json_set(preferences, '$.theme', 'light')
WHERE id = 1;
​
-- JSON数组处理
CREATE TABLE orders (
    id INTEGER PRIMARY KEY,
    customer_id INTEGER,
    items JSON -- 存储商品数组
);
​
INSERT INTO orders (customer_id, items) VALUES (
    101, 
    '[{"id":1,"name":"笔记本","price":12.5,"quantity":2},
      {"id":2,"name":"钢笔","price":45.0,"quantity":1}]'
);
​
-- 提取数组内容
SELECT o.id, json_array_length(items) as item_count,
       json_extract(items, '$[0].name') as first_item_name
FROM orders o;
​
-- 使用JSON表函数遍历数组
SELECT o.id as order_id,
       item.value->'$.name' as product_name,
       item.value->'$.price' as unit_price,
       item.value->'$.quantity' as quantity,
       (item.value->'$.price') * (item.value->'$.quantity') as subtotal
FROM orders o, json_each(o.items) as item;

注意事项:

  • JSON支持使SQLite可以处理半结构化数据

  • 对JSON的搜索没有索引支持,可能影响性能

  • 复杂JSON操作应考虑在应用层处理

  • JSON字段不会强制JSON格式验证,需要应用层保证数据有效性

4.7 加密和安全

SQLite本身不提供内置加密功能,但可通过扩展实现(如SQLCipher)。

-- 使用SQLCipher的示例(需要特殊编译版本)
-- 创建加密数据库
PRAGMA key = 'complex-password-here';
​
-- 创建表并插入敏感数据
CREATE TABLE sensitive_data (
    id INTEGER PRIMARY KEY,
    user_id INTEGER,
    credit_card TEXT,
    social_security TEXT
);
​
-- 更改密码
PRAGMA rekey = 'new-complex-password';
​
-- 导出未加密数据库(需要输入密码)
ATTACH DATABASE 'plaintext.db' AS plaintext;
SELECT sqlcipher_export('plaintext');
DETACH DATABASE plaintext;

注意事项:

  • 标准SQLite不提供内置加密功能,需要使用第三方扩展

  • 应用层加密很重要,特别是处理敏感数据时

  • 密码应该使用强哈希算法存储,并加入随机盐值

  • 敏感数据应使用强加密算法加密后再存储

  • 小心管理加密密钥,考虑使用密钥派生函数和适当的密钥轮换

5 基本使用

下面将通过代码示例展示如何使用SQLite:

import sqlite3

# 连接到SQLite数据库(如果不存在则创建)
conn = sqlite3.connect('example.db')

# 创建一个游标对象
cursor = conn.cursor()

# 创建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER,
    email TEXT UNIQUE
)
''')

# 插入数据
cursor.execute("INSERT INTO users (name, age, email) VALUES (?, ?, ?)", 
              ("张三", 30, "[email protected]"))

# 批量插入数据
users_data = [
    ("李四", 25, "[email protected]"),
    ("王五", 35, "[email protected]"),
    ("赵六", 28, "[email protected]")
]
cursor.executemany("INSERT INTO users (name, age, email) VALUES (?, ?, ?)", users_data)

# 提交事务
conn.commit()

# 查询数据
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall()
for row in rows:
    print(row)

# 条件查询
cursor.execute("SELECT * FROM users WHERE age > ?", (25,))
rows = cursor.fetchall()
print("\n年龄大于25岁的用户:")
for row in rows:
    print(row)

# 更新数据
cursor.execute("UPDATE users SET age = ? WHERE name = ?", (31, "张三"))
conn.commit()

# 删除数据
cursor.execute("DELETE FROM users WHERE name = ?", ("赵六",))
conn.commit()

# 关闭连接
conn.close()

以上就是SQLite的基础介绍, SQLite是一个功能强大且易于使用的数据库系统,特别适合嵌入式应用、移动应用以及需要便携性的场景。后续将继续讲解SQLite数据类型与SQLite函数。

参考书籍:SQLite权威指南(第二版)

你可能感兴趣的:(SQLite合集:从原理到实战,数据库,sqlite,sql,c#)