###3.6.9 使用 AUTO_INCREMENT
`AUTO_INCREMENT` 属性可用于为新记录生成唯一标识:
```sql
CREATE TABLE animals (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');
SELECT * FROM animals;
```
返回结果为:
```sql
+----+---------+
| id | name |
+----+---------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | whale |
| 6 | ostrich |
+----+---------+
```
`AUTO_INCREMENT` 列没有指定值, 所以 MySQL 会自动分配序列号. 你也可以显式的为列分配0来生成序列号, 除非启用了 [`NO_AUTO_VALUE_ON_ZERO`](https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_no_auto_value_on_zero) 模式. 例如:
```sql
INSERT INTO animals (id,name) VALUES(0,'groundhog');
```
如果列被声明为 `NOT NULL`, 也可以将 `NULL` 赋给列以生成序列号. 例如:
```sql
INSERT INTO animals (id,name) VALUES(NULL,'squirrel');
```
当你插入其它的值到 `AUTO_INCREMENT` 列, 列会被设置为该值, 序列会被重置, 以便下一个自动生成的值按照最大列值的顺序生成. 例如:
```sql
INSERT INTO animals (id,name) VALUES(100,'rabbit');
INSERT INTO animals (id,name) VALUES(NULL,'mouse');
SELECT * FROM animals;
+-----+-----------+
| id | name |
+-----+-----------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | whale |
| 6 | ostrich |
| 7 | groundhog |
| 8 | squirrel |
| 100 | rabbit |
| 101 | mouse |
+-----+-----------+
```
更新已有的 `AUTO_INCREMENT` 列的值也会重置 `AUTO_INCREMENT` 序列.
你可以使用 [`LAST_INSERT_ID()`](https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_last-insert-id) SQL 函数或者 [`mysql_insert_id()`](https://dev.mysql.com/doc/refman/8.0/en/mysql-insert-id.html) C API 函数检索最近自动生成的 `AUTO_INCREMENT` 值. 这些函数是基于连接的, 所以它们的返回值不受其他执行插入的连接的影响.
对 `AUTO_INCREMENT` 列使用最小的整数数据类型, 该列要足够大, 可以容纳所需的最大序列值. 当列达到数据类型的上限时, 尝试生成下一个序列号将会失败. 使用 `UNSIGNED` 属性允许更大的范围. 例如, 如果你使用 [`TINYINT`](https://dev.mysql.com/doc/refman/8.0/en/integer-types.html), 最大允许的序列号时 127. 对于 [`TINYINT UNSIGNED`](https://dev.mysql.com/doc/refman/8.0/en/integer-types.html), 最大值为 255. 参阅 [Section 11.2.1, “整数类型(精确值) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT”](https://dev.mysql.com/doc/refman/8.0/en/integer-types.html) 获取所有整数类型的范围.
> **[warning] 注意**
>
> 对于多行插入, [`LAST_INSERT_ID()`](https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_last-insert-id) 和 [`mysql_insert_id()`](https://dev.mysql.com/doc/refman/8.0/en/mysql-insert-id.html) 实际上从插入的*第一行*返回 `AUTO_INCREMENT` 键. 这允许在复制设置中其他服务器上正确的复制多行插入.
`AUTO_INCREMENT` 从超过 1 的值开始, 使用 [`CREATE TABLE`](https://dev.mysql.com/doc/refman/8.0/en/create-table.html) 或者 [`ALTER TABLE`](https://dev.mysql.com/doc/refman/8.0/en/alter-table.html) 设置值, 像这样:
```sql
mysql> ALTER TABLE tbl AUTO_INCREMENT = 100;
```
#### InnoDB Notes
有关在 InnoDB 中关于 `AUTO_INCREMENT` 特定用法, 参阅 [Section 15.6.1.4, “InnoDB 中的 AUTO_INCREMENT 处理”](https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html).
#### MyISAM Notes
- 对于 `MyISAM` 表, 你可以指定在多列索引的第二列上指定 `AUTO_INCREMENT`. 在本例中, `AUTO_INCREMENT` 列生成的值计算为 [`MAX(auto_increment_column) + 1 WHERE prefix=given-prefix`](https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_max). 对于你想将数据放入到有序组中时, 非常有用.
```sql
CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
```
返回结果为:
```sql
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
+--------+----+---------+
```
在本例中 (当 `AUTO_INCREMENT` 列是多列索引中的一部分时), 如果删除了任何组中 `AUTO_INCREMENT` 值最大的记录, 那么会重复使用 `AUTO_INCREMENT` 值. 即便是 `MyISAM` 表也会发生这种亲口光, `AUTO_INCREMENT` 值通常不会被重复使用.
- 如果 `AUTO_INCREMENT` 列是多列索引的一部分, MySQL 使用 `AUTO_INCREMENT` 列作为索引的开始(如果有的话)生成序列值. 例如, 如果 `animals` 表保存索引 `PRIMARY KEY (grp, id)` 和 `INDEX (id)`, MySQL 将会忽略用于生成序列值的 `PRIMARY KEY`. 因此, 该表将包含单个序列, 而不是每个 `grp` 值的序列.
#### 进一步阅读
有关 `AUTO_INCREMENT` 的更多信息请点击这里:
- 如何为列分配 `AUTO_INCREMENT` 属性: [Section 13.1.20, “CREATE TABLE 语法”](https://dev.mysql.com/doc/refman/8.0/en/create-table.html), 和 [Section 13.1.9, “ALTER TABLE 语法”](https://dev.mysql.com/doc/refman/8.0/en/alter-table.html).
- `AUTO_INCREMENT` 的行为取决于 `NO_AUTO_VALUE_ON_ZERO` SQL 模式: [Section 5.1.11, “服务器 SQL 模式](https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html).
- 如何使用 [`LAST_INSERT_ID()`](https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_last-insert-id) 函数找出包含最新 `AUTO_INCREMENT` 值的记录: [Section 12.15, “信息函数”](https://dev.mysql.com/doc/refman/8.0/en/information-functions.html).
- 设置要使用的 `AUTO_INCREMENT` 的值: [Section 5.1.8, “服务器系统变量”](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html).
- [Section 15.6.1.4, “InnoDB 中的 AUTO_INCREMENT 处理”](https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html)
- `AUTO_INCREMENT` 和复制: [Section 17.4.1.1, “复制和 AUTO_INCREMENT”](https://dev.mysql.com/doc/refman/8.0/en/replication-features-auto-increment.html).
- 与复制相关的服务器系统变量 `AUTO_INCREMENT` ([`auto_increment_increment`](https://dev.mysql.com/doc/refman/8.0/en/replication-options-master.html#sysvar_auto_increment_increment) 和 [`auto_increment_offset`](https://dev.mysql.com/doc/refman/8.0/en/replication-options-master.html#sysvar_auto_increment_offset)) : [`Section 5.1.8, “服务器系统变量”`](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html).
- 简介
- 前言和法律条款
- 安装和更新 MySQL
- 在 Linux 上安装 MySQL
- 在 Linux 上使用 APT 库安装 MySQL
- 在 Linux 上使用 Docker 部署 MySQL
- 使用 Docker 部署 MySQL 服务器的基本步骤
- 使用 Docker 部署 MySQL 服务器的更多主题
- 教程
- 连接到服务器和从服务器断开
- 输入查询
- 创建和使用数据库
- 创建和选择数据库
- 创建表
- 将数据加载到表中
- 从表中检索数据
- 选择所有数据
- 选择特定行
- 选择指定列
- 行排序
- 日期计算
- 处理 NULL 值
- 模式匹配
- 计算行数
- 使用多个表
- 获取数据库和表的信息
- 在批处理模式使用 mysql
- 常见查询示例
- 列的最大值
- 包含某一行最大值的记录
- 每组中列的最大值
- 拥有某个字段的组间最大值的行
- 使用用户自定义变量
- 使用外键
- 两个键上搜索
- 计算每日访问量
- 使用 AUTO_INCREMENT
- 在 Apache 中使用 MySQL
- MySQL 程序
- MySQL 客户端程序
- mysql — MySQL 命令行客户端
- 优化
- 优化概述
- 优化 SQL 语句
- 优化和索引
- 优化数据库结构
- 优化 InnoDB 表
- 优化 MyISAM 表
- 优化 MEMORY 表
- 理解查询执行计划
- 控制查询优化器
- 缓冲和缓存
- 优化锁操作
- 优化 MySQL 服务器
- 测量性能 (Benchmarking)
- 检查线程信息