SQLite Autoincrement(自动递增)

SQLite 中,AUTOINCREMENT 是一种用于 自动生成唯一递增 ID 的特殊关键字,通常配合 INTEGER PRIMARY KEY 使用。

它不是必须的!但在某些场景下能 避免 ID 重复


一、INTEGER PRIMARY KEY 自动递增(默认行为)

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 KEYINTEGER PRIMARY KEY AUTOINCREMENT
自动递增
删除后重用 ID
性能更高略低
维护 sqlite_sequence仅在 INSERT总是维护
推荐场景内部 ID、日志表对外暴露的 ID(订单号、用户 ID)

四、sqlite_sequence 表(自动创建)

SELECT * FROM sqlite_sequence;
nameseq
users3

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
);

需要我帮你:

  • 检查某个表是否会重用 ID
  • 迁移旧表加上 AUTOINCREMENT
  • 生成带起始 ID 的建表语句

把你的 CREATE TABLE 发我!

文章已创建 2326

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部