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;
创建表时,会自动删除表定义中 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 模式,则会导致错误。