第 40.1 节:为什么使用 ENUM?

ENUM 提供了一种为行提供属性的方法。适用于具有少量非数字选项的属性。示例:

reply ENUM('yes', 'no')
gender ENUM('male', 'female', 'other', 'decline-to-state')

值是字符串:

INSERT ... VALUES ('yes', 'female');
SELECT ... --> yes female

第 40.2 节:VARCHAR 作为替代方案

假设有:

type ENUM('fish', 'mammal', 'bird')

替代方案:

type VARCHAR(20) COMMENT "fish, bird, etc"

这种方式非常开放,可以轻松添加新类型。

与 ENUM 的比较:

  • (相同)INSERT:直接提供字符串
  • (更差)INSERT 时拼写错误不会被注意到
  • (相同)SELECT:返回实际字符串
  • (更差)占用更多空间

第 40.3 节:添加新选项

ALTER TABLE tbl MODIFY COLUMN type ENUM('fish', 'mammal', 'bird', 'insect');

注意:

  • 与所有 MODIFY COLUMN 的情况一样,必须包含 NOT NULL 以及最初存在的任何其他限定符,否则它们会丢失。
  • 如果你添加到列表末尾且列表项少于 256 个,ALTER 仅通过更改模式完成。也就是说,不会进行冗长的表复制。(旧版本的 MySQL 没有此优化。)

第 40.4 节:NULL 与 NOT NULL

展示当 NULL 和 bad-value 存储到可为空和不可为空列时发生的情况。同时通过 +0 转换为数值来查看存储的内容。

CREATE TABLE enum (
    e ENUM('yes', 'no') NOT NULL,
    enull ENUM('x', 'y', 'z') NULL
);

INSERT INTO enum (e, enull) VALUES
('yes', 'x'),
('no', 'y'),
(NULL, NULL),
('bad-value', 'bad-value');
-- Query OK, 4 rows affected, 3 warnings

SHOW WARNINGS;

结果:

+---------+------+--------------------------------------------+
| Level   | Code | Message                                    |
+---------+------+--------------------------------------------+
| Warning | 1048 | Column 'e' cannot be null                  |
| Warning | 1265 | Data truncated for column 'e' at row 4     |
| Warning | 1265 | Data truncated for column 'enull' at row 4 |
+---------+------+--------------------------------------------+

查看表中实际存储的内容(使用 +0 转换为数值):

SELECT e, e+0 FROM enum;

结果:

+------+-----+
| e    | e+0 |
+------+-----+
| yes  | 1   |
| no   | 2   |
|      | 0   |   -- 因为 NULL 被转换为空字符串,然后转为 0
|      | 0   |   -- 'bad-value' 被转换为 0
+------+-----+
SELECT enull, enull+0 FROM enum;

结果:

+-------+---------+
| enull | enull+0 |
+-------+---------+
| x     | 1       |
| y     | 2       |
| NULL  | NULL    |
|       | 0       |   -- 'bad-value' 被转换为 0
+-------+---------+