SQLite 是一个非常流行且强大的嵌入式关系型数据库管理系统。它与其他数据库(如 MySQL、PostgreSQL)最大的不同在于,它不是一个独立的服务器进程,而是以库的形式被集成到应用程序中。这意味着 SQLite 数据库是一个单一的文件,易于部署、备份和传输。它零配置、无服务器、自包含的特性,使其成为移动应用、桌面应用、小型网站、物联网设备以及开发测试等场景的理想选择。

“轻量级却不失强大,SQLite 让数据库操作变得前所未有的简单。”


一、什么是 SQLite?

SQLite 是一个 C 语言库,实现了一个小型、快速、自包含的 SQL 数据库引擎。它的名字“Lite”就说明了它的轻量级特性。

核心特点:

  • 无服务器 (Serverless): 与传统的客户端-服务器模式数据库不同,SQLite 应用程序直接读写磁盘上的数据库文件,无需独立的数据库服务器进程。
  • 零配置 (Zero-configuration): 无需安装、配置或管理。你只需直接使用其库。
  • 自包含 (Self-contained): 作为一个单一的文件,整个数据库都存储在这个文件中。
  • 事务支持 (Transactional): 完全支持 ACID (Atomicity, Consistency, Isolation, Durability) 特性,确保数据完整性。
  • SQL 标准 (SQL Standard): 遵循大部分 SQL92 标准,支持常见的 SQL 语句。
  • 跨平台 (Cross-platform): 可以在几乎所有操作系统上运行,包括 Windows, macOS, Linux, Android, iOS 等。

常见应用场景:

  • 移动应用:Android 和 iOS 内置 SQLite 作为本地数据存储。
  • 桌面应用:如 Firefox、Chrome 浏览器、Skype 等使用 SQLite 存储数据。
  • 小型网站:流量不大的网站可以使用 SQLite 作为后端数据库。
  • 物联网设备:资源受限的设备非常适合。
  • 嵌入式系统:各种设备中作为本地数据存储。
  • 开发测试:作为快速原型开发和测试的本地数据库。

二、安装与入门

SQLite 无需传统意义上的“安装”。你只需要下载其命令行工具或将其库集成到你的项目中。

1. 下载 SQLite 命令行工具

访问 SQLite 官方网站:https://www.sqlite.org/download.html

“Precompiled Binaries for …” 部分,根据你的操作系统下载对应的文件。

  • Windows: 下载 sqlite-tools-win32-x86-...zip。解压后会得到 sqlite3.exe (或 sqlite.exe) 文件。将其路径添加到系统环境变量 PATH 中,或者直接在解压目录中使用。
  • macOS / Linux: 通常系统会自带 sqlite3。如果没有,可以下载 sqlite-tools-linux-x86-...zip 并解压,或者通过包管理器安装:
    • macOS (Homebrew): brew install sqlite
    • Ubuntu/Debian: sudo apt-get install sqlite3
    • Fedora/CentOS: sudo yum install sqlite

2. 启动 SQLite 命令行界面 (CLI)

打开命令行/终端,输入 sqlite3

  • 创建新数据库文件或连接现有数据库:
    1
    sqlite3 mydatabase.db
    如果 mydatabase.db 不存在,它会被创建。如果存在,则会连接到该数据库。
  • 不指定数据库文件,进入内存模式(数据库内容不会保存):
    1
    sqlite3

进入 CLI 后,你会看到 sqlite> 提示符。

3. SQLite CLI 特殊命令 (以 . 开头)

sqlite> 提示符下,除了标准的 SQL 语句,你还可以使用一些以 . 开头的内置命令来管理数据库。

  • .help: 显示帮助信息。
  • .databases: 列出当前连接的数据库。
  • .tables: 列出当前数据库中的所有表。
  • .schema <table_name>: 显示表的创建 SQL 语句。
  • .quit.exit: 退出 SQLite CLI。
  • .mode <mode>: 设置输出模式 (e.g., list, csv, column)。
  • .headers on/off: 开启/关闭列名显示。
  • .open <filename>: 关闭当前数据库并打开另一个数据库。
  • .read <filename>: 从文件中执行 SQL 语句。
  • .dump: 导出整个数据库为 SQL 脚本。

示例:

1
2
3
4
5
6
7
sqlite> .databases
main: /path/to/mydatabase.db

sqlite> .tables
# 暂时没有表

sqlite> .quit

三、基本 SQL 操作

SQLite 遵循标准的 SQL 语法。下面是一些基本的 SQL 操作示例。

1. 创建表 (CREATE TABLE)

创建一个名为 users 的表,包含 id, name, email 字段。

1
2
3
4
5
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE
);
  • INTEGER PRIMARY KEY AUTOINCREMENT: id 将是一个自动递增的整数主键。
  • TEXT: 字符串类型。
  • NOT NULL: 字段不能为 NULL。
  • UNIQUE: 字段值必须唯一。

在 CLI 中执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
sqlite> CREATE TABLE users (
...> id INTEGER PRIMARY KEY AUTOINCREMENT,
...> name TEXT NOT NULL,
...> email TEXT UNIQUE
...> );
sqlite> .tables
users
sqlite> .schema users
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE
);

2. 插入数据 (INSERT INTO)

users 表插入几条记录。

1
2
3
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com');
INSERT INTO users (name, email) VALUES ('Charlie', 'charlie@example.com');

3. 查询数据 (SELECT)

  • 查询所有字段所有记录:
    1
    SELECT * FROM users;
  • 查询特定字段:
    1
    SELECT name, email FROM users;
  • 按条件查询:
    1
    2
    SELECT * FROM users WHERE id = 1;
    SELECT * FROM users WHERE name LIKE 'A%'; -- 名字以 A 开头的用户
  • 排序:
    1
    SELECT * FROM users ORDER BY name ASC; -- 按名字升序
  • 限制结果:
    1
    SELECT * FROM users LIMIT 1 OFFSET 1; -- 跳过第一条,取第二条

在 CLI 中执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sqlite> INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
sqlite> INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com');
sqlite> INSERT INTO users (name, email) VALUES ('Charlie', 'charlie@example.com');

sqlite> .mode column
sqlite> .headers on
sqlite> SELECT * FROM users;
id name email
---------- ---------- -----------------
1 Alice alice@example.com
2 Bob bob@example.com
3 Charlie charlie@example.com

sqlite> SELECT name FROM users WHERE id = 2;
name
----------
Bob

4. 更新数据 (UPDATE)

修改 id 为 1 的用户的邮箱。

1
UPDATE users SET email = 'alice.new@example.com' WHERE id = 1;

验证:

1
2
3
4
sqlite> SELECT * FROM users WHERE id = 1;
id name email
---------- ---------- --------------------
1 Alice alice.new@example.com

5. 删除数据 (DELETE FROM)

删除 id 为 2 的用户。

1
DELETE FROM users WHERE id = 2;

验证:

1
2
3
4
5
sqlite> SELECT * FROM users;
id name email
---------- ---------- --------------------
1 Alice alice.new@example.com
3 Charlie charlie@example.com

6. 删除表 (DROP TABLE)

删除整个 users 表。

1
DROP TABLE users;

四、数据类型

SQLite 支持的 SQL 数据类型非常灵活。与其他数据库不同,SQLite 采用的是动态类型系统。这意味着你可以在任何列中存储任何类型的值。

SQLite 提供了以下五种主要的数据类型(Storage Classes):

  1. NULL: 值是 NULL。
  2. INTEGER: 带符号的整数,根据大小存储为 1, 2, 3, 4, 6 或 8 字节。
  3. REAL: 浮点数值,存储为 8 字节的 IEEE 浮点数。
  4. TEXT: 字符串,以 UTF-8, UTF-16BE 或 UTF-16LE 编码存储。
  5. BLOB: 二进制大对象,存储为原始字节数据。

重要概念:Type Affinity (类型亲和性)

当你创建表时指定的类型(例如 INT, VARCHAR, DATETIME)在 SQLite 中被称为 Type Affinity。它只是一个建议,并不强制特定类型的存储。

例如:

  • INTEGER, INT, BIGINT 都会被赋予 INTEGER 亲和性。
  • TEXT, VARCHAR, NVARCHAR 都会被赋予 TEXT 亲和性。
  • REAL, DOUBLE, FLOAT 都会被赋予 REAL 亲和性。
  • BLOB 会被赋予 BLOB 亲和性。
  • DATETIME, BOOLEAN 等没有直接对应的存储类,它们通常会根据亲和性存为 TEXTINTEGER

示例:
即使将列定义为 INTEGER,你仍然可以尝试插入字符串:

1
2
3
4
5
6
7
8
9
CREATE TABLE mixed_data (
id INTEGER PRIMARY KEY,
my_int_col INTEGER,
my_text_col TEXT
);

INSERT INTO mixed_data (my_int_col, my_text_col) VALUES (123, 'Hello');
INSERT INTO mixed_data (my_int_col, my_text_col) VALUES ('abc', 'World'); -- 仍然可以插入!
INSERT INTO mixed_data (my_int_col, my_text_col) VALUES (3.14, 456); -- 浮点数会被截断或转换为整数

建议: 尽管 SQLite 具有动态类型,但为了数据的一致性和可预测性,强烈建议在创建表时为列指定合理的类型,并在插入数据时遵循这些类型

五、索引 (Indexes)

索引是提高查询速度的关键手段。为经常用于 WHERE 子句、JOIN 条件或 ORDER BY 子句的列创建索引。

1
CREATE INDEX idx_users_email ON users (email);
  • 主键 (PRIMARY KEY) 列会自动创建唯一索引。
  • UNIQUE 约束也会自动创建唯一索引。

六、事务 (Transactions)

事务是数据库操作的原子性、一致性、隔离性和持久性 (ACID) 的保证。SQLite 完全支持事务。

1
2
3
4
5
6
7
BEGIN TRANSACTION;  -- 或者 BEGIN; 或 BEGIN DEFERRED;
-- 执行一系列 SQL 语句
INSERT INTO ...;
UPDATE ...;
-- 如果有错误或需要回滚
-- ROLLBACK;
COMMIT; -- 提交所有更改
  • BEGIN TRANSACTION: 开始一个事务。
  • COMMIT: 提交事务,所有更改永久保存。
  • ROLLBACK: 回滚事务,所有更改被撤销,数据库回到事务开始前的状态。

示例:

1
2
3
4
5
sqlite> BEGIN;
sqlite> INSERT INTO users (name, email) VALUES ('David', 'david@example.com');
sqlite> SELECT * FROM users; -- 在当前事务中可见 David
sqlite> ROLLBACK;
sqlite> SELECT * FROM users; -- David 被回滚,不再可见

七、与编程语言集成

SQLite 的强大之处在于它可以方便地集成到各种编程语言中。以下是一些常见语言的示例:

1. Node.js

使用 sqlite3 模块。

1
npm install sqlite3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('./mydatabase.db'); // 连接数据库

db.serialize(() => {
db.run("CREATE TABLE IF NOT EXISTS greetings (id INTEGER PRIMARY KEY, message TEXT)");

const stmt = db.prepare("INSERT INTO greetings (message) VALUES (?)");
for (let i = 0; i < 10; i++) {
stmt.run("Hello world " + i);
}
stmt.finalize();

db.all("SELECT id, message FROM greetings", [], (err, rows) => {
if (err) {
throw err;
}
rows.forEach((row) => {
console.log(`${row.id}: ${row.message}`);
});
});
});

db.close((err) => {
if (err) {
console.error(err.message);
}
console.log('Close the database connection.');
});

2. Python

使用内置的 sqlite3 模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import sqlite3

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

# 创建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
price REAL
)
''')

# 插入数据
cursor.execute("INSERT INTO products (name, price) VALUES (?, ?)", ('Laptop', 1200.00))
cursor.executemany("INSERT INTO products (name, price) VALUES (?, ?)",
[('Mouse', 25.50), ('Keyboard', 75.00)])
conn.commit() # 提交事务

# 查询数据
cursor.execute("SELECT * FROM products WHERE price > ?", (50,))
rows = cursor.fetchall()

for row in rows:
print(row)

# 更新数据
cursor.execute("UPDATE products SET price = ? WHERE name = ?", (1300.00, 'Laptop'))
conn.commit()

# 关闭连接
conn.close()

3. Java

使用 JDBC 驱动(需要下载 sqlite-jdbc.jar 并添加到项目中)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.sql.*;

public class SQLiteDemo {
public static void main(String[] args) {
String url = "jdbc:sqlite:mydatabase.db"; // 数据库文件路径

try (Connection conn = DriverManager.getConnection(url)) {
if (conn != null) {
DatabaseMetaData meta = conn.getMetaData();
System.out.println("The driver name is " + meta.getDriverName());
System.out.println("A new database has been connected.");

Statement stmt = conn.createStatement();
// 创建表
stmt.execute("CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY, name TEXT)");

// 插入数据
stmt.execute("INSERT INTO tasks (name) VALUES ('Learn SQLite')");
stmt.execute("INSERT INTO tasks (name) VALUES ('Write Markdown')");

// 查询数据
ResultSet rs = stmt.executeQuery("SELECT id, name FROM tasks");
while (rs.next()) {
System.out.println(rs.getInt("id") + "\t" +
rs.getString("name"));
}
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}

八、高级特性和注意事项

1. 外键约束 (Foreign Keys)

SQLite 默认情况下不强制执行外键约束。你需要手动启用它。

1
PRAGMA foreign_keys = ON;

这条语句需要在每次连接到数据库时执行 (PRAGMA 是 SQLite 的特殊命令)。

然后就可以创建带外键的表:

1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE IF NOT EXISTS categories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE
);

CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT,
category_id INTEGER,
FOREIGN KEY (category_id) REFERENCES categories (id)
);

2. JOIN 操作

连接多个表进行查询。

1
2
3
4
5
6
7
SELECT
p.title,
c.name AS category_name
FROM
posts AS p
JOIN
categories AS c ON p.category_id = c.id;

3. 用户权限/安全

SQLite 没有内置的用户账户和权限管理系统。所有连接到数据库文件的程序都具有对该文件的完全读写权限(取决于操作系统文件系统权限)。因此,安全需要通过文件系统权限、应用程序逻辑或加密来保证。

4. 并发性 (Concurrency)

SQLite 支持并发读写,但在并发写入方面有一些限制。

  • 多个读者可以同时访问数据库。
  • 只有一个写入者可以在任何给定时间写入数据库。

当一个进程尝试写入时,它会获取一个写锁。其他写入尝试会等待,直到锁被释放。在高并发写入场景下,这可能成为性能瓶颈。对于需要高并发写入的场景,传统的客户端-服务器数据库(如 PostgreSQL, MySQL)是更好的选择。

5. 加密

SQLite 本身不提供数据加密功能。要加密 SQLite 数据库,你需要使用第三方扩展(如 SQLCipher)或在应用程序层面进行数据加密。

6. 可视化工具

除了命令行,还有许多图形界面工具可以方便地管理 SQLite 数据库:

  • DB Browser for SQLite: 免费、开源,功能强大,跨平台。强烈推荐。
  • DataGrip (JetBrains): 商业多数据库 IDE,支持 SQLite。
  • VS Code 扩展: 许多 VS Code 扩展也支持 SQLite 数据库的浏览和查询。

九、总结

SQLite 以其独特的嵌入式、零配置、无服务器特性,在众多数据库中独树一帜。它非常适合那些资源受限、不需要高并发写入、或需要简单部署和管理的应用场景。从移动应用到桌面软件,再到小型个人项目,SQLite 都展现了其作为一款强大而又轻量级数据库的优秀品质。

掌握 SQLite 的基本操作和特性,将大大拓宽你的技术栈,并为许多项目中数据存储问题提供一个简单而高效的解决方案。