SQLite 约束:INTEGER PRIMARY KEY 与 ROWID

目录

[ROWID 的基本概念](#ROWID 的基本概念)

[INTEGER PRIMARY KEY 的机制](#INTEGER PRIMARY KEY 的机制)

[INTEGER PRIMARY KEY 的潜在问题](#INTEGER PRIMARY KEY 的潜在问题)

[AUTOINCREMENT 的工作方式](#AUTOINCREMENT 的工作方式)

使用场景的选择建议

关键差异总结


ROWID 的基本概念

SQLite 中的 ROWID 是一个隐藏列,用于标识表中的每一行。其本质是一个 64 位整数,通常由 SQLite 引擎自动分配。如果没有显式的主键定义,ROWID 会成为行的唯一标识。例如:

sql 复制代码
CREATE TABLE packages (recipient TEXT, address TEXT);

隐藏的 ROWID 结构如下:

ROWID recipient address
1 张三 北京市朝阳区
2 李四 上海市浦东区

INTEGER PRIMARY KEY 的机制

定义 INTEGER PRIMARY KEY 的列会直接映射到 ROWID。这种设计提供了高效的查询性能。例如:

sql 复制代码
CREATE TABLE express (
    express_id INTEGER PRIMARY KEY,
    recipient TEXT,
    address TEXT
);

插入数据时,未指定的 express_id 会自动分配为 ROWID 值:

sql 复制代码
INSERT INTO express (recipient, address) VALUES ('张三', '北京'); -- express_id=1
INSERT INTO express (recipient, address) VALUES ('李四', '上海'); -- express_id=2

性能优势体现在底层直接通过内存地址定位数据,避免额外索引开销。

INTEGER PRIMARY KEY 的潜在问题

删除记录后可能导致 ID 重用。例如:

sql 复制代码
DELETE FROM express WHERE express_id=2;
INSERT INTO express (recipient, address) VALUES ('王五', '广州'); -- express_id 可能为2

这种特性适用于临时数据或日志系统,但对于需要严格唯一性的场景(如银行流水)存在风险。

AUTOINCREMENT 的工作方式

AUTOINCREMENT 确保 ID 严格递增且不被重用。其实现依赖 sqlite_sequence 表记录当前最大 ID。例如:

sql 复制代码
CREATE TABLE bank_flow (
    flow_id INTEGER PRIMARY KEY AUTOINCREMENT,
    amount REAL,
    time TEXT
);

操作示例:

  1. 初始插入记录的 flow_id 为 1 和 2;
  2. 删除 flow_id=2 后;
  3. 新插入记录的 flow_id 强制为 3。

性能影响主要来自每次插入需查询和更新 sqlite_sequence 表。

使用场景的选择建议

  • 临时数据/日志系统

    选择 INTEGER PRIMARY KEY,允许 ID 重用以提升性能。

  • 金融交易/订单系统

    选择 INTEGER PRIMARY KEY AUTOINCREMENT,确保 ID 唯一性和递增性。

  • 非整数主键场景

    避免使用 TEXT 主键,因其查询效率显著低于整数类型。

关键差异总结

特性 INTEGER PRIMARY KEY AUTOINCREMENT
ID 重用 允许 禁止
性能 更高(直接使用 ROWID) 较低(需维护序列表)
适用场景 日志/临时数据 订单/金融记录

通过快递单号和银行流水的场景对比,清晰展示了两者在实现唯一标识时的不同取舍。

相关推荐
风一样的美狼子3 小时前
仓颉语言 LinkedList 链表实现深度解析
java·服务器·前端
zero13_小葵司3 小时前
JavaScript 性能优化系列(六)接口调用优化 - 6.4 错误重试策略:智能重试机制,提高请求成功率
开发语言·javascript·ecmascript
DARLING Zero two♡3 小时前
Profile-Guided Optimization(PGO):Rust 性能优化的终极武器
开发语言·性能优化·rust
橘子师兄3 小时前
c++中list详解
开发语言·c++
万邦科技Lafite8 小时前
京东按图搜索京东商品(拍立淘) API (.jd.item_search_img)快速抓取数据
开发语言·前端·数据库·python·电商开放平台·京东开放平台
默 语9 小时前
MySQL中的数据去重,该用DISTINCT还是GROUP BY?
java·数据库·mysql·distinct·group by·1024程序员节·数据去重
Never_Satisfied10 小时前
在JavaScript / Node.js / 抖音小游戏中,使用tt.request通信
开发语言·javascript·node.js
爱吃小胖橘10 小时前
Unity资源加载模块全解析
开发语言·unity·c#·游戏引擎
oDeviloo11 小时前
新版IntelliJ IDEA个性化设置兼容老版习惯
java·ide·intellij-idea