










INTEGER PRIMARY KEY 是 ROWID 的“唯一门牌号”在 SQLite 中,除 WITHOUT ROWID 表外,每一张表都有一个隐藏的 64 位有符号整型列,名叫 ROWID。这个 ROWID 自带自增功能,且插入数据时如果不指定,它会自动分配。
SQLite 的语法解析器(Parser)在设计时,被硬编码了一条特殊规则:
只有当列声明的类型恰好是
INTEGER,并且该列是PRIMARY KEY时,这一列才会被标记为“ROWID 的别名(Alias)”。
这意味着,当你在查询中写 WHERE id = 5 时,SQLite 内部实际上是在直接操作 ROWID,拥有极快的 B-Tree 查找速度。但如果你写的是 INT:
解析器一看:哦,这不是 INTEGER,只是一个普通的整数列。
即使你写了 AUTOINCREMENT,它也不会触发 ROWID 别名机制,而是把它当成一个普普通通的 INT 主键来存储。
INT、BIGINT 也当成 ROWID 别名?这是设计上的严谨性考量。
ROWID 在底层存储中,固定占用 8 字节(64位),取值范围是 -9223372036854775808 到 9223372036854775807。
如果你用 INT,在 SQLite 中它虽然也是整数类型,但 SQLite 是动态类型,INT 在大多数其他数据库中代表“标准整数”(可能是 4 字节)。
SQLite 的作者(D. Richard Hipp)为了避免歧义和潜在的溢出陷阱,决定只承认唯一的 INTEGER 这个单词作为开启 ROWID 别名的“钥匙”。如果允许 BIGINT 或 INT 都去绑定 ROWID,那么当某些从 MySQL 迁移来的表用 BIGINT 时,可能会因为字节长度理解不同而产生混乱。
这是 SQLite 诞生之初就定下的“规矩”。官方文档(CREATE TABLE 章节)写得非常明确:
"A column declared
INTEGER PRIMARY KEYis an alias for the ROWID."
(声明为INTEGER PRIMARY KEY的列是 ROWID 的别名。)
文档只字未提 INT 或 BIGINT。这个规则被写死在 SQLite 的词法分析器里,属于硬编码的特殊处理(Special Case),而不是通用的类型亲和性(Type Affinity)规则。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。