惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
Google DeepMind News
Google DeepMind News
腾讯CDC
V
Visual Studio Blog
Engineering at Meta
Engineering at Meta
博客园 - 司徒正美
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tailwind CSS Blog
Vercel News
Vercel News
爱范儿
爱范儿
Last Week in AI
Last Week in AI
G
Google Developers Blog
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
有赞技术团队
有赞技术团队
D
DataBreaches.Net
博客园_首页
J
Java Code Geeks
云风的 BLOG
云风的 BLOG
V
V2EX
A
About on SuperTechFans
H
Hackread – Cybersecurity News, Data Breaches, AI and More
人人都是产品经理
人人都是产品经理

博客园 - StationaryTraveller

如何查找微软VS软件中的图标 Qt动态获取翻译文本 Windows判断某窗口是否被其他窗口完全覆盖 MFC实现一个通用模态进度条窗口 如何批量修改“后期生成事件”为“预生成事件” MFC对话框中如何给一个控件发送消息 Window剪切板 C语言根据函数指针偏移实现函数动态调用 Qt程序系统文本翻译 SVN创建分支 Qt多版本如何共存 Qt6编译的程序在某些win10系统报错 电脑忘机了用户名密码怎么办 Qt事件过滤器实现空闲检测 CMFCToolTipCtrl的AddTool导致内存增加 MFC中CBitmap、CBrush、CFont、CPalette、CPen、CRgn删除GDI对象问题 实现从QListWidgett拖拽项到QTableWidget Windows系统下通过命令行获取进程指标 命令模式实现撤销和重做机制 避免溢出求平均值的算法 字节流转16进制字符串 PImpl:Pointer to Implementation C++单例
SQLite 的自增(AUTOINCREMENT)强制要求列的数据类型必须是I...
StationaryTraveller · 2026-07-13 · via 博客园 - StationaryTraveller

1. 核心原因: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 主键来存储。

2. 为什么不能把 INTBIGINT 也当成 ROWID 别名?

这是设计上的严谨性考量。

  • ROWID 在底层存储中,固定占用 8 字节(64位),取值范围是 -92233720368547758089223372036854775807

  • 如果你用 INT,在 SQLite 中它虽然也是整数类型,但 SQLite 是动态类型,INT 在大多数其他数据库中代表“标准整数”(可能是 4 字节)。

  • SQLite 的作者(D. Richard Hipp)为了避免歧义和潜在的溢出陷阱,决定只承认唯一的 INTEGER 这个单词作为开启 ROWID 别名的“钥匙”。如果允许 BIGINTINT 都去绑定 ROWID,那么当某些从 MySQL 迁移来的表用 BIGINT 时,可能会因为字节长度理解不同而产生混乱。

3. 历史原因与文档约定

这是 SQLite 诞生之初就定下的“规矩”。官方文档(CREATE TABLE 章节)写得非常明确:

"A column declared INTEGER PRIMARY KEY is an alias for the ROWID."
(声明为 INTEGER PRIMARY KEY 的列是 ROWID 的别名。)

文档只字未提 INTBIGINT。这个规则被写死在 SQLite 的词法分析器里,属于硬编码的特殊处理(Special Case),而不是通用的类型亲和性(Type Affinity)规则。