🗄️ 第四章 管理数据-避免非法数据的功能
📄 一句话概括

AUTO_INCREMENT 让数据库自动发号:插入时不用给编号,数据库自己按 1、2、3……往下排——编号这种「程序最不该手工管」的事,交给机器最稳当。

📝 本节和前面几节的关系

编号列就是 4-12 主键最常用的形状。本节还带一个环境注记:AUTO_INCREMENT 是 MySQL 的写法,前面三章一直在用的在线 SQLite 环境里对应的是 AUTOINCREMENT(或干脆用 INTEGER PRIMARY KEY 的隐式发号)——Demo 里两种都给。

一、为什么编号不该手工管

自己维护编号的问题:两个人同时插入怎么办?删掉一条后号怎么补?手工管迟早出乱子。数据库的答案:

-- MySQL 写法
CREATE TABLE students (
    id    INT AUTO_INCREMENT PRIMARY KEY,
    name  VARCHAR(20)
);

INSERT INTO students (name) VALUES ('张三');   -- 不给 id
INSERT INTO students (name) VALUES ('李四');   -- 也不给
-- id 自动是 1、2

二、SQLite 环境的对应写法

本课 Demo 用的在线 SQLite 环境:

-- SQLite 写法(三选一)
CREATE TABLE s1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20));
CREATE TABLE s2 (id INTEGER PRIMARY KEY, name VARCHAR(20));   -- 隐式自增(推荐)

INTEGER PRIMARY KEY 在 SQLite 里天生就是自动发号——插 NULL 或省略都行,编号从 1 开始递增。名字不同、脾气一样。

三、发号规则三件事

  1. 只增不补:删掉 id=3,下一条还是从最大号 +1 开始发,不会回头填 3
  2. 并发安全:两人同时插入,数据库保证各拿各的号,绝不撞车
  3. 不要依赖连续性:删除、事务回滚(4-16)都会留空洞;业务若要求「发票号必须连续」,用别的机制,别指望自增列

四、动手 Demo:删了不回头

CREATE TABLE t (id INTEGER PRIMARY KEY, name VARCHAR(20));

INSERT INTO t (name) VALUES ('甲');   -- id=1
INSERT INTO t (name) VALUES ('乙');   -- id=2
INSERT INTO t (name) VALUES ('丙');   -- id=3

DELETE FROM t WHERE id = 3;
INSERT INTO t (name) VALUES ('丁');   -- id=4,不是 3!

SELECT * FROM t;
id   name
1    甲
2    乙
4    丁

3 号位永远空着——发号器只前进,不回头。

五、30 秒实验

显式插一个超大号 INSERT INTO t VALUES (100, '大号'),再省略 id 插一条——下一条自动是 101:计数器以最大值为准。(有些实现允许插入指定号并会更新计数器,视数据库而定。)

六、常见误区

自测三问 1. MySQL 和 SQLite 的自动编号分别怎么写?(AUTO_INCREMENT / INTEGER PRIMARY KEY 隐式自增) 2. 删掉 3 号后下一条是几号?(最大号 +1,不是 3) 3. 为什么不能拿自增列当发票号?(不保证连续——删除与回滚都留洞)

相关笔记