SQLite 是世界上部署范围最广的关系型数据库管理系统,以"嵌入式、零配置、单文件"著称,被内置在几乎所有智能手机、浏览器和桌面应用中。本教程将介绍 SQLite 在 Windows 环境下的安装流程、命令行基本使用,以及在 Python 中操作 SQLite 数据库的方法;全程与系列教程中已介绍的 MySQL 进行类比分析,帮助已有 MySQL 基础的读者快速理解两者的异同,并为后续 AI 应用开发中常见的本地数据存储需求打下基础。

前置教程

如想快速开始学习本教程,你可能需要先完成以下前置教程:

资源下载

1. SQLite 是什么:先看懂它与 MySQL 的架构差异

1.1 什么是 SQLite

SQLite 是一个嵌入式的开源关系型数据库引擎。与 MySQL 不同,SQLite 无需单独安装、启动和管理,它本身是一个以 C 语言编写的程序库:应用程序把它链接进来,就获得了完整的数据库能力。

SQLite 的核心特征可以概括为三句话:

  • 数据库即文件:一个 SQLite 数据库就是磁盘上的一个 .db 文件,复制文件就等于备份了整个数据库。
  • 零配置:没有安装向导、没有初始化步骤、没有账号密码、没有监听端口,打开文件即可使用。
  • 无处不在:它采用公共领域授权(Public Domain),可免费用于任何用途,Android、iOS、Chrome、微信等海量软件内部都内置了 SQLite,这使它成为世界上部署数量最多的数据库引擎。

在 AI/ML 工具链中,SQLite 同样随处可见:LangChain、LlamaIndex 默认使用 SQLite 存储文档元数据,许多本地 Agent 工具用 SQLite 保存会话历史,部分轻量级向量数据库方案也构建在 SQLite 之上。后续学习 RAG 与 Agent 相关教程时,你会经常与它打交道。

1.2 架构对比:无服务的嵌入式 vs 客户端-服务器

SQLite 与 MySQL 最本质的区别在于架构。MySQL 是典型的客户端-服务器(C/S)架构:mysqld 服务进程常驻后台,监听 3306 端口,任何客户端都要通过 TCP 连接、账号密码认证后才能访问数据。SQLite 则是嵌入式架构:数据库引擎直接嵌入应用程序进程内,对数据库文件进行本地读写,中间没有服务进程,也没有网络环节。

graph LR subgraph MySQL架构["MySQL:客户端-服务器架构"] M1["应用程序
(数据库客户端)"] -->|"TCP 连接,端口 3306
需用户名密码认证"| M2["mysqld 服务进程
常驻后台"] M2 --> M3["数据目录
多个数据文件"] end subgraph SQLite架构["SQLite:嵌入式架构"] S1["应用程序
内嵌 SQLite 引擎"] -->|"进程内直接读写
无需认证"| S2["单个 .db 文件
数据库即文件"] end style M2 fill:#d6eaf8 style S2 fill:#d5f5e3

架构差异带来了使用体验上的一系列连锁差别:

使用环节 MySQL SQLite
安装 安装服务软件,数百 MB 解压一个几 MB 的压缩包
启动 需注册并启动 Windows 服务 无服务,随应用程序启停
连接 TCP 连接 + 用户名密码认证 直接打开文件
备份 导出 SQL 转储文件 复制一个文件
权限 root 账号 + GRANT/REVOKE 体系 无用户体系,取决于文件系统权限
远程访问 天然支持多客户端远程连接 不支持,需应用层自行封装接口

1.3 选型建议:什么时候用 SQLite,什么时候用 MySQL

SQLite 和 MySQL 各有擅长的场景,选型的核心依据是数据由谁访问、从哪里访问:

场景 推荐数据库 原因
桌面应用、单机工具的数据存储 SQLite 零配置,无需用户安装数据库服务
移动 App 本地数据 SQLite 移动端事实标准,系统内置
原型验证、课程示例、测试环境 SQLite 一分钟上手,随时删库重来
AI 应用的会话记录、元数据、缓存 SQLite 数据量中小、单进程访问为主
多用户 Web 服务的业务数据 MySQL 高并发读写、远程连接、权限管理
需要细粒度账号权限管理的系统 MySQL 内置用户与授权体系
多台服务器共享读写同一份数据 MySQL 客户端-服务器架构天然支持

简单判断:数据只被一个应用在本机读写,选 SQLite;数据要被多个用户、多台机器通过网络访问,选 MySQL。

2. 安装与配置 SQLite

2.1 安装方式选择

SQLite 官网不提供传统意义的"安装程序",只提供编译好的命令行工具压缩包。Windows 环境下有两种推荐安装方式:

安装方式 适用场景 推荐度
Winget 命令行安装 快速安装,自动配置 PATH 首选推荐
官网 zip 手动安装 需要指定版本或固定安装位置 备选

2.2 通过 Winget 安装(推荐)

Windows 10/11 系统默认自带 Winget 工具。以管理员身份打开 PowerShell,执行以下命令确认 Winget 可用:

winget --version

有版本号输出即可。随后执行安装命令:

winget install SQLite.SQLite

安装完成后,关闭当前终端并重新打开一个新终端(让 PATH 生效),进入下一节验证。

2.3 通过官网压缩包手动安装(备选)

如果无法使用 Winget,可从 SQLite 官网下载页面 获取工具包;网络环境不佳时,可直接从上方网盘地址下载(sqlite-tools 3.53.4 命令行工具包):

  1. 在页面中找到 sqlite-tools-win-x64 分类,下载对应的 zip 压缩包(约几 MB)
  2. 将压缩包解压到一个固定目录,例如 C:\sqlite
  3. 将该目录添加到系统环境变量 PATH 中

添加 PATH 的方式与 MySQL的安装与基本使用教程 中配置环境变量的步骤完全一致,可直接参考其"添加 MySQL 到系统 PATH"一节。命令行方式如下(需管理员权限):

[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "Machine") + ";C:\sqlite", "Machine")

执行后同样需要重新打开终端使配置生效。

2.4 验证安装

在新打开的终端中执行:

sqlite3 --version

预期输出类似:

3.53.4 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc (64-bit)

能正常显示版本号,说明 SQLite 命令行工具已就绪。

注意:Python 标准库中的 sqlite3 模块与这里的命令行工具是两回事。即便不安装命令行工具,Python 也自带 SQLite 引擎;但要在终端中直接敲 SQL 学习,仍需按本节安装命令行工具。

2.5 安装流程对比:SQLite 究竟省掉了什么

回顾 MySQL的安装与基本使用教程 的完整流程,再把 SQLite 的安装流程放在旁边,两者的工作量差异一目了然:

环节 MySQL SQLite
下载 MSI 安装包,数百 MB zip 压缩包,几 MB
安装 安装向导,数分钟 解压即用
环境变量 需手动添加 bin 目录到 PATH 需手动添加工具目录到 PATH
初始化 mysqld --initialize 初始化数据目录 无需初始化,首次连接自动建库
系统服务 注册 Windows 服务并启动 无服务进程
账号密码 初始化生成临时密码,首次登录后修改 无用户体系,无需认证
字符集 需配置 utf8mb4 避免中文乱码 TEXT 恒为 UTF-8,无需配置

SQLite 把 MySQL 安装过程中的初始化、服务、密码、字符集四个环节全部省去,这正是"零配置"的含义。代价则是它不提供网络服务能力,无法像 MySQL 那样被多台机器远程共享。

3. SQLite 基本使用

3.1 连接数据库:打开一个文件

MySQL 连接数据库的命令是 mysql -u root -p,需要输入密码;SQLite 连接数据库就是打开一个文件:

sqlite3 ai_ml_tutorial.db

执行后终端提示符变为 sqlite>,表示已进入 SQLite 交互环境。如果 ai_ml_tutorial.db 文件不存在,SQLite 会自动创建它——这一点与 MySQL 不同,MySQL 需要先执行 CREATE DATABASE 建库再 USE 切换,而 SQLite 把"建库"简化成了"创建一个文件"。

本教程沿用系列教程的数据约定,使用 ai_ml_tutorial 作为数据库名(即文件 ai_ml_tutorial.db),并沿用 MySQL 教程中的 users 表和数据,便于逐项对照学习。

进入交互环境后,可用点命令确认当前连接的数据库:

.databases

输出中的 main 就是当前打开的 ai_ml_tutorial.db 文件。如果中途想切换到另一个数据库文件,无需退出,使用 .open 命令:

.open another.db

3.2 点命令:SQLite 的"元命令"体系

sqlite3 命令行客户端提供了一批以 . 开头的点命令,用于查看元数据、调整输出格式等客户端操作。注意区分:点命令不属于 SQL 语言,结尾不加分号;而 SQL 语句仍然以分号结尾。

先打开表头显示和表格化输出,让查询结果更像 MySQL 客户端的效果:

.headers on
.mode box
需求 SQLite 点命令 MySQL 中的做法
查看当前连接的数据库 .databases SELECT DATABASE();
查看所有表 .tables SHOW TABLES;
查看表结构 .schema users DESC users;
查看建表语句 .schema users SHOW CREATE TABLE users;
查看帮助 .help 查阅官方文档
退出客户端 .quit 或 .exit EXIT;

MySQL 的 SHOW DATABASES、SHOW TABLES、DESC 等都是 SQL 语句;SQLite 的对应功能则由点命令承担。这是命令行使用中两边最大的习惯差异,记住"点命令看元数据,SQL 语句管数据"即可。

3.3 创建数据表:建表语句逐项对照

在 sqlite> 提示符下执行以下建表语句:

CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT NOT NULL UNIQUE,
    age INTEGER DEFAULT 0,
    created_at TEXT DEFAULT CURRENT_TIMESTAMP
);

把它与 MySQL 教程中的建表语句并排放置,差异一目了然:

CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    age INT DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
差异点 MySQL 写法 SQLite 写法
自增主键 INT AUTO_INCREMENT PRIMARY KEY INTEGER PRIMARY KEY AUTOINCREMENT
字符串类型 VARCHAR(50),超长报错 TEXT,长度仅作声明不强制
时间类型 DATETIME 独立类型 惯用 TEXT 存 ISO 格式字符串

关于自增主键需要展开说明:SQLite 要求自增列的类型必须写成 INTEGER(不能写成 INT),因为 INTEGER PRIMARY KEY 是行号 rowid 的别名,本身就具备自增能力;末尾的 AUTOINCREMENT 关键字只是额外保证"已删除行的编号不会被复用",日常使用可以省略。而 MySQL 中 AUTO_INCREMENT 是实现自增的必要关键字,两者心智模型不同。

用 .schema users 确认建表结果:

.schema users

3.4 数据的增删改查(CRUD)

建表之后的数据操作,SQLite 与 MySQL 的语法几乎完全一致,以下语句可原样运行在两边:

-- 插入数据
INSERT INTO users (name, email, age) VALUES
    ('张三', 'zhangsan@example.com', 25),
    ('李四', 'lisi@example.com', 30),
    ('王五', 'wangwu@example.com', 28);

-- 查询所有数据
SELECT * FROM users;

-- 条件查询 + 排序 + 分页
SELECT * FROM users WHERE age >= 25 ORDER BY age DESC LIMIT 2 OFFSET 0;

-- 更新数据
UPDATE users SET age = 26 WHERE name = '张三';

-- 删除数据
DELETE FROM users WHERE name = '王五';

-- 删除表
DROP TABLE users;

已掌握 MySQL 的读者可以直接把增删改查的 SQL 搬进 SQLite 使用。两个数据库的真正差异集中在"库怎么建、元数据怎么看、类型怎么定"这些外围操作上,核心 SQL 能力完全通用。此外,事务语法(BEGIN、COMMIT、ROLLBACK)和 LIKE 模糊查询在两边也完全一致。

3.5 数据类型与亲和性:最容易被低估的差异

MySQL 的列类型是强约束:声明为 INT 的列写入字符串会报错或被强制转换。SQLite 采用类型亲和性(Type Affinity)机制:建表时声明的类型只是给存储引擎的"建议",实际几乎可以存入任何类型的数据。SQLite 底层只有 5 种存储类型:NULL、INTEGER、REAL(浮点数)、TEXT、BLOB。

列声明的类型按以下规则映射到亲和性:

列声明中含有的字符串 亲和性 示例
INT INTEGER INT、BIGINT 均归为 INTEGER
CHAR、CLOB、TEXT TEXT VARCHAR(50)、TEXT 均归为 TEXT
BLOB 或未声明类型 BLOB 原样存储
REAL、FLOA、DOUB REAL DOUBLE、FLOAT 均归为 REAL
其余情况 NUMERIC 尽可能转为数值存储

据此可以整理出一张 MySQL 到 SQLite 的类型迁移对照表:

MySQL 类型 SQLite 惯用写法 说明
INT / BIGINT INTEGER 自增主键必须写 INTEGER
VARCHAR(N) TEXT 长度 N 不强制校验
DATETIME TEXT 惯用 ISO 8601 字符串
DECIMAL(M,D) NUMERIC 或 REAL 无精确定点类型,金额计算需注意精度
TINYINT(1)(布尔) INTEGER 用 0 和 1 表示假和真
BLOB BLOB 一致

这是把 MySQL 应用迁移到 SQLite 时最容易踩的坑:SQLite 对列中存储的数据类型来者不拒,脏数据要靠应用层校验。反过来,这也让 SQLite 的表结构非常灵活,不需要因为"字段加长"而修改表定义。

4. 与 MySQL 的差异对照手册

4.1 常用命令速查表

将本教程涉及的命令汇总成一张速查表,便于从 MySQL 快速切换到 SQLite:

操作 MySQL SQLite
连接数据库 mysql -u root -p sqlite3 ai_ml_tutorial.db
查看所有数据库 SHOW DATABASES; .databases(一个文件即一个库)
选择数据库 USE mydb; 打开文件即选中,或 ATTACH 'x.db' AS x;
查看所有表 SHOW TABLES; .tables
查看表结构 DESC users; .schema users
查看建表语句 SHOW CREATE TABLE users; .schema users
查看当前时间 SELECT NOW(); SELECT datetime('now','localtime');
字符串拼接 CONCAT(a, b) a \|\| b
退出客户端 EXIT; .quit 或 .exit

4.2 语法细节差异

除速查表中的命令差异外,还有几处 SQL 语法细节值得留意:

  • 当前时间函数:MySQL 用 NOW();SQLite 用 datetime('now') 返回 UTC 时间,加 localtime 修饰符返回本地时间。SQLite 还提供了 date()、time()、strftime() 等日期函数家族。
  • 标识符引用:MySQL 惯用反引号包住表名列名(如 `order`);SQLite 推荐双引号(如 "order"),同时也兼容反引号。
  • 存储过程与调度:MySQL 支持存储过程、事件调度器;SQLite 均不支持,业务逻辑需放在应用层实现。全文检索方面,SQLite 需启用 FTS5 扩展模块。
  • 表结构修改:MySQL 可用 ALTER TABLE ... MODIFY COLUMN 随意改列类型;SQLite 的 ALTER TABLE 仅支持改名、加列和删列,修改列类型需要"新建表、复制数据、删旧表、重命名"四步操作。

4.3 权限与并发模型差异

权限方面,MySQL 拥有完整的用户体系:root 账号、GRANT/REVOKE 授权、按库表粒度控制访问。SQLite 没有任何用户和权限概念,谁能读写数据库文件,完全由操作系统的文件权限决定。因为没有监听端口,SQLite 也不存在"数据库端口被扫描爆破"这类攻击面,安全性边界清晰。

并发方面,两者差异更大:MySQL 的 InnoDB 引擎支持大量连接同时写入,行级锁让不同行的修改互不阻塞;SQLite 在同一时刻只允许一个写事务,多个连接的写入操作会串行排队,后来的写入者在锁被占用时会收到"database is locked"错误。读取方面,SQLite 默认模式下读写互斥,启用 WAL(Write-Ahead Logging)模式后,读操作可与写操作并发进行:

PRAGMA journal_mode=WAL;

单机、低频写入是 SQLite 的舒适区;一旦出现"多个进程频繁写同一个库"的需求,就需要更换为 MySQL 或其他数据库了。

4.4 从 MySQL 迁移到 SQLite 的注意事项

把一个基于 MySQL 的项目改为 SQLite 存储(或反向迁移)时,按以下清单逐项核对:

  • 时间字段:MySQL 的 DATETIME DEFAULT CURRENT_TIMESTAMP 填的是服务器本地时区时间;SQLite 的 CURRENT_TIMESTAMP 填的是 UTC 时间,比北京时间早 8 小时。否则会出现迁移后时间"慢了 8 小时"的问题。
  • 类型校验前移:SQLite 不校验列类型,原本依赖 MySQL 报错兜底的数据质量检查,需要移到应用层。
  • 存储过程改写:MySQL 中的存储过程和调度事件无法迁移,需改写为应用代码。
  • 并发写入评估:确认新场景下是否有多进程并发写需求,必要时启用 WAL 模式并设置 busy_timeout。
  • 数据导入:从 MySQL 导出的 INSERT 语句大多可直接在 SQLite 中执行,导入前去除 SQLite 不支持的函数(如 NOW() 改为 datetime('now'))即可。

5. 在 Python 中使用 SQLite

5.1 标准库自带,无需安装驱动

MySQL 教程中操作数据库需要先 pip install mysql-connector-python 安装第三方驱动;Python 则将 SQLite 引擎直接内置在标准库中,import sqlite3 即可使用。

对比项 Python + SQLite Python + MySQL
驱动来源 标准库 sqlite3,无需安装 第三方 mysql-connector-python
连接参数 一个文件路径 host、port、user、password、database
SQL 占位符 ? %s
建库前提 文件不存在时自动创建 需先 CREATE DATABASE

5.2 连接与增删改查示例

本教程配套了一个示例项目 sqlite-demo:一个基于标准库的命令行增删改查工具,支持 init(建表并写入示例数据)、add、list、find、update、delete 六个子命令,可从资源下载区的网盘地址获取。项目结构如下:

sqlite-demo/
├── sqlite_demo.py   # 命令行工具入口
└── README.md        # 运行说明

其核心代码片段如下:

import sqlite3

# 连接数据库(文件不存在时自动创建)
conn = sqlite3.connect("ai_ml_tutorial.db")
cursor = conn.cursor()

# 建表
cursor.execute("""
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT NOT NULL UNIQUE,
    age INTEGER DEFAULT 0,
    created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
""")

# 插入数据,占位符为问号,可防止 SQL 注入
cursor.execute(
    "INSERT INTO users (name, email, age) VALUES (?, ?, ?)",
    ("张三", "zhangsan@example.com", 25)
)
conn.commit()

# 查询数据
cursor.execute("SELECT * FROM users WHERE age >= ?", (20,))
for row in cursor.fetchall():
    print(row)

# 让查询结果支持按列名访问
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute("SELECT name, age FROM users")
for row in cursor.fetchall():
    print(row["name"], row["age"])

# 关闭连接
conn.close()

与 MySQL 驱动的用法相比,有三处习惯差异需要适应:连接参数从一个文件路径取代了五项服务器配置;SQL 占位符从 %s 换成了 ?;增删改之后同样需要 conn.commit() 提交事务。

完整代码请查看网盘资源中的 sqlite-demo/sqlite_demo.py。使用方式:

python sqlite_demo.py init                              # 建表并写入三条示例数据
python sqlite_demo.py add --name 赵六 --email zhaoliu@example.com --age 22
python sqlite_demo.py list                              # 列出全部用户
python sqlite_demo.py find --keyword 张                 # 按姓名或邮箱模糊查找
python sqlite_demo.py update --name 张三 --age 26       # 按姓名修改年龄
python sqlite_demo.py delete --name 王五                # 按姓名删除用户

如果你想把 MySQL 教程中的 fastapi-mysql 前后端项目改造为 SQLite 版本,只需替换连接代码和占位符,其余业务 SQL 几乎可以原样保留,这也是验证"SQL 能力通用"的好练习。

6. 可视化管理工具

与 MySQL 生态中的 HeidiSQL 对应,SQLite 最常用的免费图形化工具是 DB Browser for SQLite:开源、跨平台、安装即用,从官网下载安装后,点击"打开数据库"选择 .db 文件即可开始管理。

工具界面围绕三个选项卡组织,可以对应 HeidiSQL 的功能来理解:

  • 数据库结构:查看和修改表结构,相当于 HeidiSQL 的"编辑表"
  • 浏览数据:像 Excel 一样直接增删改单元格,相当于 HeidiSQL 的"编辑数据"
  • 执行 SQL:输入并运行 SQL 语句,相当于 HeidiSQL 的"查询"选项卡

此外,HeidiSQL 本身也支持 SQLite:在会话的"网络类型"中选择 SQLite,指定数据库文件路径即可连接。对于已经在使用 HeidiSQL 管理 MySQL 的读者,可以零成本复用既有工具。

7. 总结

7.1 核心内容回顾

  • SQLite 是嵌入式关系型数据库:无服务进程、无端口、无账号体系,一个 .db 文件就是一个完整数据库,复制文件即完成备份。
  • 安装极简:通过 winget install SQLite.SQLite 或官网压缩包即可获得命令行工具,相比 MySQL 省去了初始化、服务、密码、字符集四个环节。
  • 命令行使用中,元数据查看靠点命令(.tables、.schema、.quit),与 MySQL 的 SHOW、DESC 体系一一对应。
  • 增删改查 SQL 与 MySQL 几乎完全一致;差异集中在类型系统(类型亲和性)、自增主键写法、时间函数时区和并发写入模型上。
  • Python 标准库自带 sqlite3 模块,连接参数、占位符写法与 MySQL 驱动不同,业务 SQL 可直接复用。
  • 选型口诀:单机单应用选 SQLite,多用户多机器网络访问选 MySQL。

7.2 常见问题与解答

问:SQLite 能完全替代 MySQL 吗?

答:不能一概而论。SQLite 没有服务进程和用户权限体系,不适合多用户远程访问、高并发写入的场景;但对于单机应用、移动端存储、原型验证和低流量网站,SQLite 更简单可靠。两者是互补关系,很多项目的做法是开发测试阶段用 SQLite、生产环境用 MySQL。

问:SQLite 数据库如何实现远程访问?

答:SQLite 本质是对本地文件的读写,不提供网络协议。如需远程访问,通常由应用服务器(如 FastAPI 后端)封装 HTTP 接口对外提供服务,多个客户端通过网络调用接口间接读写数据。

问:为什么我插入的时间比本地时间早了 8 小时?

答:SQLite 的 CURRENT_TIMESTAMP 和 datetime('now') 返回的都是 UTC 时间,而 MySQL 的 CURRENT_TIMESTAMP 使用服务器本地时区。需要本地时间时改用 datetime('now', 'localtime'),或读取数据后自行换算时区。

问:一个 .db 文件相当于 MySQL 的一个库,那怎么同时打开多个库?

答:使用 ATTACH DATABASE '文件路径' AS 别名; 可以在同一连接中挂载多个数据库文件,之后用"别名.表名"跨库访问,用 .databases 查看当前挂载的所有库。

问:往 TEXT 列里插入数字、往 INTEGER 列里插入字符串会报错吗?

答:不会。SQLite 的类型亲和性机制不强制校验列类型,几乎任何值都能存进去。这与 MySQL 的强类型约束不同,数据合法性检查需要在应用层完成。