一个 ENUM
是一个字符串对象,其值从在创建表时在列规范中显式枚举的允许值列表中选择。
有关 ENUM
类型语法和长度限制,请参阅 第 13.3.1 节,“字符串数据类型语法”。
ENUM
类型具有以下优点
在列具有有限数量的可能值的场景中,可以实现紧凑的数据存储。您指定为输入值的字符串会自动编码为数字。有关
ENUM
类型的存储要求,请参阅 第 13.7 节,“数据类型存储要求”。可读的查询和输出。这些数字在查询结果中会转换回相应的字符串。
以及以下需要考虑的潜在问题
枚举值必须是带引号的字符串文字。例如,您可以使用以下代码创建包含 ENUM
列的表
CREATE TABLE shirts (
name VARCHAR(40),
size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
);
INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),
('polo shirt','small');
SELECT name, size FROM shirts WHERE size = 'medium';
+---------+--------+
| name | size |
+---------+--------+
| t-shirt | medium |
+---------+--------+
UPDATE shirts SET size = 'small' WHERE size = 'large';
COMMIT;
将 100 万行插入到此表中,其值为 'medium'
,将需要 100 万字节的存储空间,而如果将实际字符串 'medium'
存储在 VARCHAR
列中,则需要 600 万字节的存储空间。
每个枚举值都有一个索引
列规范中列出的元素将被分配索引号,从 1 开始。
空字符串错误值的索引值为 0。这意味着您可以使用以下
SELECT
语句查找已分配无效ENUM
值的行mysql> SELECT * FROM tbl_name WHERE enum_col=0;
NULL
值的索引为NULL
。这里的术语 “索引” 指的是枚举值列表中的位置。它与表索引无关。
例如,指定为 ENUM('Mercury', 'Venus', 'Earth')
的列可以具有以下所示的任何值。每个值的索引也显示在其中。
值 | 索引 |
---|---|
NULL |
NULL |
'' |
0 |
'Mercury' |
1 |
'Venus' |
2 |
'Earth' |
3 |
一个 ENUM
列最多可以有 65,535 个不同的元素。
如果您在数字上下文中检索 ENUM
值,则将返回列值的索引。例如,您可以使用以下代码从 ENUM
列中检索数值
mysql> SELECT enum_col+0 FROM tbl_name;
例如 SUM()
或 AVG()
等需要数值参数的函数,如果需要,会将参数强制转换为数字。对于 ENUM
值,索引号将用于计算。
创建表时,会自动从表定义中 ENUM
成员值的尾随空格中删除尾随空格。
检索时,存储到 ENUM
列中的值将使用列定义中使用的字母大小写显示。请注意,ENUM
列可以分配字符集和排序规则。对于二进制或区分大小写的排序规则,在将值分配到列时会考虑字母大小写。
如果您将数字存储到 ENUM
列中,该数字将被视为可能值列表中的索引,并且存储的值是具有该索引的枚举成员。(但是,这 不适用于 LOAD DATA
,它将所有输入视为字符串。)如果数字值被引用,并且在枚举值列表中没有匹配的字符串,则它仍然被解释为索引。出于这些原因,不建议定义具有看起来像数字的枚举值的 ENUM
列,因为这很容易造成混淆。例如,以下列具有字符串值为 '0'
、'1'
和 '2'
的枚举成员,但数字索引值为 1
、2
和 3
numbers ENUM('0','1','2')
如果您存储 2
,它将被解释为索引值,并将变为 '1'
(具有索引 2 的值)。如果您存储 '2'
,它将与枚举值匹配,因此它将被存储为 '2'
。如果您存储 '3'
,它将不与任何枚举值匹配,因此它将被视为索引,并将变为 '2'
(具有索引 3 的值)。
mysql> INSERT INTO t (numbers) VALUES(2),('2'),('3');
mysql> SELECT * FROM t;
+---------+
| numbers |
+---------+
| 1 |
| 2 |
| 2 |
+---------+
要确定 ENUM
列的所有可能值,请使用 SHOW COLUMNS FROM
并解析输出的 tbl_name
LIKE 'enum_col
'Type
列中的 ENUM
定义。
在 C API 中,ENUM
值将作为字符串返回。有关使用结果集元数据来区分它们与其他字符串的信息,请参阅 C API 基本数据结构。
在某些情况下,枚举值也可以是空字符串 (''
) 或 NULL
如果您将无效值插入到
ENUM
中(即,列表中不存在的字符串),则将插入空字符串作为特殊的错误值。此字符串可以通过其数字值为 0 的事实与 “正常” 空字符串区分开来。有关枚举值的数字索引的详细信息,请参阅 枚举文字的索引值。如果启用了严格 SQL 模式,则尝试插入无效的
ENUM
值会导致错误。如果
ENUM
列被声明为允许NULL
,则NULL
值是该列的有效值,并且默认值为NULL
。如果ENUM
列被声明为NOT NULL
,则其默认值为允许值列表中的第一个元素。
ENUM
值根据其索引号排序,索引号取决于枚举成员在列规范中列出的顺序。例如,对于 ENUM('b', 'a')
,'b'
排在 'a'
之前。空字符串排在非空字符串之前,NULL
值排在所有其他枚举值之前。
为了防止在 ENUM
列上使用 ORDER BY
子句时出现意外结果,请使用以下技术之一
按字母顺序指定
ENUM
列表。通过编码
ORDER BY CAST(
或col
AS CHAR)ORDER BY CONCAT(
,确保列按字母顺序排序,而不是按索引号排序。col
)
枚举值不能是表达式,即使是计算结果为字符串值的表达式也不行。
例如,此 CREATE TABLE
语句 无法 工作,因为 CONCAT
函数不能用于构造枚举值
CREATE TABLE sizes (
size ENUM('small', CONCAT('med','ium'), 'large')
);
您也不能使用用户变量作为枚举值。这两条语句 无法 工作
SET @mysize = 'medium';
CREATE TABLE sizes (
size ENUM('small', @mysize, 'large')
);
我们强烈建议您 不要 使用数字作为枚举值,因为这并不会节省相对于适当的 TINYINT
或 SMALLINT
类型而言的存储空间,如果您错误地引用了 ENUM
值,很容易将字符串和底层数字值(可能不相同)混淆。如果您确实使用数字作为枚举值,请始终将其括在引号中。如果省略了引号,数字将被视为索引。请参阅 处理枚举文字,了解即使是带引号的数字也可能被错误地用作数字索引值的方式。
定义中的重复值会导致警告,如果启用了严格 SQL 模式,则会导致错误。