SQLite 数据库就是一个文件
如果你用过 MySQL 或 Postgres,你会习惯先运行 CREATE DATABASE myapp;,然后由服务器在某个看不见的地方管理这个新数据库。SQLite 不是这样工作的。它没有服务器,也没有 CREATE DATABASE 语句。一个数据库就是磁盘上的一个普通文件,扩展名通常是 .db、.sqlite 或 .sqlite3,但扩展名只是惯例。
要创建数据库,只需把 sqlite3 工具指向一个还不存在的文件名:
sqlite3 mydata.db
就这么简单。如果 mydata.db 不存在,SQLite 就准备好创建它;如果已经存在,SQLite 就打开它。两种情况用的是同一条命令。这个心智模型更接近“打开一份文档”,而不是“启动一台数据库服务器”。
写入数据之前,文件不会出现
有一件事常常让人困惑。运行上面的命令,输入 .quit,然后看看你的目录:文件并不在那里。
SQLite 很“懒”。在有内容可写之前,它不会费事在磁盘上创建文件。一旦你创建了表或提交了数据,文件就出现了:
现在 mydata.db 已经存在于磁盘上了。在第一次写入之前,这个“数据库”只存在于连接的内存中。这偶尔会让人困惑,但偶尔也很有用,因为这意味着中途放弃的会话不会留下任何痕迹。
用命令行创建数据库
在一个新的终端里,完整流程如下:
$ sqlite3 mydata.db
SQLite version 3.45.0
Enter ".help" for usage hints.
sqlite> CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);
sqlite> .databases
main: /home/you/mydata.db r/w
sqlite> .quit
在命令行里还有几个好用的命令:
.databases:列出已附加的数据库及其文件路径。.tables:列出当前数据库中的表。.schema:显示所有对象的CREATE TABLE语句。.quit:退出。
如果你已经在 sqlite3 里但没有打开任何文件(启动时没带参数),可以用 .open 打开一个文件:
sqlite> .open mydata.db
规则相同:文件不存在就创建,存在就打开。
“If Not Exists”是内置的
用过其他数据库的人常担心:如果文件已经存在怎么办?会不会把它覆盖掉?不会。打开一个已有的文件就只是打开它,什么都不会被覆盖。与 CREATE DATABASE IF NOT EXISTS 最接近的做法,就是直接打开文件。SQLite 用同一条命令处理这两种情况。
如果你确实想从头开始,先删掉这个文件:
rm mydata.db
sqlite3 mydata.db
不过要确定这真是你想要的。这一步无法撤销,也没有管理工具能帮你恢复。
用 Python 创建数据库
大多数时候你不会待在命令行里,而是在应用代码中创建数据库。Python 的标准库自带 sqlite3 模块,无需安装:
sqlite3.connect("mydata.db") 遵循和命令行一样的规则:文件不存在就创建,存在就打开。其他所有语言的绑定(Node 的 better-sqlite3、Go 的 database/sql 驱动、Rust 的 rusqlite 等)也都是这样工作的,因为它们底层封装的都是同一个 C 库。
Python 还有一个专门的捷径:把 ":memory:" 作为路径传入,就会得到一个完全存在于内存中的数据库,连接关闭时它就消失了。这是下一页的内容。
文件应该放在哪里?
既然数据库是一个文件,“该放在哪里”就是一个实际的问题。几条经验法则:
- 对于应用程序:放在用户数据目录或应用工作目录下的某处。在可执行文件所在路径不可写的系统上,不要把数据库放在可执行文件旁边。
- 对于项目:放在仓库根目录或
data/文件夹中。如果它保存的是本地状态,就把它加到.gitignore里,把二进制数据库提交到 Git 很少有好结果。 - 对于测试:使用
:memory:或临时文件,又快又能自动清理。
权限也很重要。运行进程的用户需要对数据库文件“以及”它的父目录都有读写权限(SQLite 在写入时会在数据库旁边创建锁文件)。
快速验证一下
要确认整个流程从头到尾都能正常工作:
你应该会看到返回两行。如果这能运行,说明数据库文件已经存在,表结构在里面,数据也可以查询。这就是 SQLite“创建数据库”的全部内容:没有服务器,没有用户,没有权限表,只有一个文件。
下一篇:内存数据库
同样是创建文件的 sqlite3.connect(...) 调用,只要换个参数,就能创建一个完全不碰磁盘的数据库。内存数据库是运行测试、快速设计表结构原型或保存临时数据最快的方式。接下来就讲它。
常见问题
如何在 SQLite 中创建数据库?
在终端中运行 sqlite3 mydata.db。如果文件 mydata.db 不存在,SQLite 会创建它;如果已经存在,就打开它。SQLite 没有单独的 CREATE DATABASE 语句,数据库“就是”这个文件。
SQLite 有 CREATE DATABASE 命令吗?
没有。与 MySQL 或 Postgres 不同,SQLite 没有 CREATE DATABASE SQL 语句。只要把 sqlite3(或者 Python 的 sqlite3 模块这样的客户端库)指向一个还不存在的文件名,数据库就创建好了。
为什么我新建的 SQLite 数据库文件是空的,或者根本不存在?
SQLite 很“懒”:在你创建第一张表或提交一个事务之前,它不会真正把文件写到磁盘上。如果你只是运行 sqlite3 mydata.db 然后退出,是不会出现任何文件的。创建一张表或运行 .databases,文件就会出现。
如何用 Python 创建 SQLite 数据库?
导入内置的 sqlite3 模块,调用 sqlite3.connect('mydata.db')。如果文件不存在,会自动创建。如果把路径写成 ':memory:',得到的则是一个临时的内存数据库。