CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT
);
行为
说明
自动递增
插入 NULL 时,SQLite 自动分配 未使用过的最大 ROWID + 1
可手动指定
插入具体值时使用该值
允许重复?
删除后,ID 可能被重用
示例:
INSERT INTO users (name) VALUES ('Alice'); -- id = 1
INSERT INTO users (name) VALUES ('Bob'); -- id = 2
DELETE FROM users WHERE id = 1;
INSERT INTO users (name) VALUES ('Charlie'); -- id = 1(重用!)
二、AUTOINCREMENT:严格递增
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);
行为
说明
严格递增
永远使用 历史最大值 + 1,绝不重用 已删除的 ID
性能略低
需维护 sqlite_sequence 表
从 1 开始
初始值为 1
示例:
INSERT INTO users (name) VALUES ('Alice'); -- id = 1
INSERT INTO users (name) VALUES ('Bob'); -- id = 2
DELETE FROM users WHERE id = 1;
INSERT INTO users (name) VALUES ('Charlie'); -- id = 3(不重用!)
三、对比总结
特性
INTEGER PRIMARY KEY
INTEGER PRIMARY KEY AUTOINCREMENT
自动递增
✅
✅
删除后重用 ID
✅
❌
性能
更高
略低
维护 sqlite_sequence
仅在 INSERT 时
总是维护
推荐场景
内部 ID、日志表
对外暴露的 ID(订单号、用户 ID)
四、sqlite_sequence 表(自动创建)
SELECT * FROM sqlite_sequence;
name
seq
users
3
seq = 当前最大分配 ID AUTOINCREMENT 依赖此表保证不重用
五、手动控制自增起始值
-- 让下一个 ID 从 1000 开始
INSERT INTO sqlite_sequence (name, seq) VALUES ('users', 999)
ON CONFLICT(name) DO UPDATE SET seq = 999;
或重建表时指定:
CREATE TABLE orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
...
) WITHOUT ROWID; -- 不推荐,AUTOINCREMENT 无效
六、常见误区
误区
真相
AUTOINCREMENT 必须用
❌ 普通 INTEGER PRIMARY KEY 已足够 90% 场景
AUTOINCREMENT 更快
❌ 略慢,因需查 sqlite_sequence
删除后 ID 永远不重用
⚠️ 只有加 AUTOINCREMENT 才不重用
可用于非主键列
❌ 只能用于 INTEGER PRIMARY KEY
七、实际应用建议
场景
推荐写法
用户表、订单表(对外 ID)
id INTEGER PRIMARY KEY AUTOINCREMENT
日志表、缓存表(内部用)
id INTEGER PRIMARY KEY
导入旧数据需保留 ID
手动 INSERT INTO ... VALUES (100, 'name')
八、完整示例
-- 推荐:对外用户表
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 推荐:内部日志表
CREATE TABLE login_logs (
id INTEGER PRIMARY KEY, -- 不加 AUTOINCREMENT
user_id INT,
ip TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 插入测试
INSERT INTO users (name, email) VALUES ('Alice', 'a@example.com'); -- id=1
INSERT INTO users (name, email) VALUES ('Bob', 'b@example.com'); -- id=2
DELETE FROM users WHERE id = 1;
INSERT INTO users (name, email) VALUES ('Charlie', 'c@example.com'); -- id=3
九、查看当前自增状态
-- 查看所有表的自增计数
SELECT * FROM sqlite_sequence;
-- 查看表结构确认
PRAGMA table_info(users);
十、性能影响(微小)
操作
无 AUTOINCREMENT
有 AUTOINCREMENT
插入
快
略慢(查 seq)
内存
少
多维护一个表
并发
高
略低(锁 seq)
实际影响 < 5%,优先考虑业务正确性
总结:何时用 AUTOINCREMENT?
条件
是否使用
ID 会暴露给用户/前端
✅
需要防重用(如订单号)
✅
纯内部表、日志表
❌
追求极致性能
❌
最佳实践一览
-- 对外表:用 AUTOINCREMENT
CREATE TABLE invoices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
amount DECIMAL,
user_id INT
);
-- 内部表:省略
CREATE TABLE temp_cache (
id INTEGER PRIMARY KEY,
data TEXT
);