8.4 中文镜像

MySQL 8.4 参考手册 · 中文镜像

正文为中文,英文原文默认隐藏。点击任意中文段落即可展开 / 收起对应英文原文。

打开官方英文原文 ↗

译文由机器翻译生成,仅供理解参考;有疑问请以官方英文原文为准。

中文点击中文段落可显示 / 隐藏英文原文本页译文覆盖 91%

13.3.5 ENUM 类型13.3.5 The ENUM Type

ENUM 是一种字符串对象,其值从一列允许的值中选择,这些值在创建表时在列规范中明确列出。An ENUM is a string object with a value chosen from a list of permitted values that are enumerated explicitly in the column specification at table creation time.

请参见 第 13.3.1 节,“字符串数据类型语法” 了解 ENUM 类型的语法和长度限制。See Section 13.3.1, “String Data Type Syntax” for ENUM type syntax and length limits.

ENUM 类型具有以下优点:The ENUM type has these advantages:

  • 在列的可能值有限的情况下进行紧凑数据存储。您指定为输入值的字符串会自动编码为数字。有关 ENUM 类型的存储要求,请参阅 第 13.7 节,“数据类型存储要求”。Compact data storage in situations where a column has a limited set of possible values. The strings you specify as input values are automatically encoded as numbers. See Section 13.7, “Data Type Storage Requirements” for storage requirements for the ENUM type.

  • 可读的查询和输出。数字已转回查询结果中对应的字符串。Readable queries and output. The numbers are translated back to the corresponding strings in query results.

以及需要考虑的这些潜在问题:and these potential issues to consider:

  • 如果你创建的枚举值看起来像数字,很容易将字面值与它们的内部索引号混淆,如枚举限制中所解释的那样。If you make enumeration values that look like numbers, it is easy to mix up the literal values with their internal index numbers, as explained in Enumeration Limitations.

  • 在ENUM子句中使用ORDER BY列需要额外注意,如枚举排序中所解释的那样。Using ENUM columns in ORDER BY clauses requires extra care, as explained in Enumeration Sorting.

创建和使用 ENUM 列Creating and Using ENUM Columns

枚举值必须是带引号的字符串字面量。例如,你可以这样创建一个包含ENUM列的表:An enumeration value must be a quoted string literal. For example, you can create a table with an ENUM column like this:

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 万字节。Inserting 1 million rows into this table with a value of 'medium' would require 1 million bytes of storage, as opposed to 6 million bytes if you stored the actual string 'medium' in a VARCHAR column.

枚举字面量的索引值Index Values for Enumeration Literals

每个枚举值都有一个索引:Each enumeration value has an index:

  • 在列规范中列出的元素被分配索引号,从 1 开始。The elements listed in the column specification are assigned index numbers, beginning with 1.

  • 空字符串错误值的索引值为 0。这意味着您可以使用以下 SELECT 语句查找被分配了无效 ENUM 值的行:The index value of the empty string error value is 0. This means that you can use the following SELECT statement to find rows into which invalid ENUM values were assigned:

    mysql> SELECT * FROM tbl_name WHERE enum_col=0;
    
  • NULL 值的索引是 NULL。The index of the NULL value is NULL.

  • 此处的 “索引” 一词是指在枚举值列表中的位置。它与表索引无关。The term “index” here refers to a position within the list of enumeration values. It has nothing to do with table indexes.

例如,指定为 ENUM('Mercury', 'Venus', 'Earth') 的列可以具有此处显示的任意值。每个值的索引也显示如下。For example, a column specified as ENUM('Mercury', 'Venus', 'Earth') can have any of the values shown here. The index of each value is also shown.

价值Value 索引Index
NULL NULL
'' 0
'Mercury' 1
'Venus' 2
'Earth' 3

ENUM 列可以有最多 65,535 个不同的元素。An ENUM column can have a maximum of 65,535 distinct elements.

如果在数值上下文中检索 ENUM 值,则会返回列值的索引。例如,你可以像这样从 ENUM 列中检索数值:If you retrieve an ENUM value in a numeric context, the column value's index is returned. For example, you can retrieve numeric values from an ENUM column like this:

mysql> SELECT enum_col+0 FROM tbl_name;

诸如 SUM() 或 AVG() 之类需要数值参数的函数,如果有必要,会将参数强制转换为数字。对于 ENUM 值,计算中使用索引号。Functions such as SUM() or AVG() that expect a numeric argument cast the argument to a number if necessary. For ENUM values, the index number is used in the calculation.

枚举字面量的处理Handling of Enumeration Literals

在创建表时,表定义中 ENUM 成员值的尾随空格会自动删除。Trailing spaces are automatically deleted from ENUM member values in the table definition when a table is created.

当检索时,存储在 ENUM 列中的值将使用列定义中使用的字母大小写显示。请注意,ENUM 列可以指定字符集和校对规则。对于二进制或区分大小写的校对规则,在向列分配值时会考虑字母大小写。When retrieved, values stored into an ENUM column are displayed using the lettercase that was used in the column definition. Note that ENUM columns can be assigned a character set and collation. For binary or case-sensitive collations, lettercase is taken into account when assigning values to the column.

如果您将一个数字存储到ENUM列中,该数字将被视为可能值的索引,存储的值是具有该索引的枚举成员。(然而,这在多线程系统中与LOAD DATA, which treats all input as strings.) If the numeric value is quoted, it is still interpreted as an index if there is no matching string in the list of enumeration values. For these reasons, it is not advisable to define an ENUM具有看起来像数字的枚举值的列,因为这很容易引起混淆。例如,下面的列具有字符串值的枚举成员'0', '1',以及'2',但数值索引值为1, 2,以及3:If you store a number into an ENUM column, the number is treated as the index into the possible values, and the value stored is the enumeration member with that index. (However, this does not work with LOAD DATA, which treats all input as strings.) If the numeric value is quoted, it is still interpreted as an index if there is no matching string in the list of enumeration values. For these reasons, it is not advisable to define an ENUM column with enumeration values that look like numbers, because this can easily become confusing. For example, the following column has enumeration members with string values of '0', '1', and '2', but numeric index values of 1, 2, and 3:

numbers ENUM('0','1','2')

如果你存储 2,它会被解释为索引值,并变为 '1'(索引为 2 的值)。如果你存储 '2',它会匹配一个枚举值,因此它被存储为 '2'。如果你存储 '3',它不匹配任何枚举值,因此会被当作索引处理,并变为 '2'(索引为 3 的值)。If you store 2, it is interpreted as an index value, and becomes '1' (the value with index 2). If you store '2', it matches an enumeration value, so it is stored as '2'. If you store '3', it does not match any enumeration value, so it is treated as an index and becomes '2' (the value with index 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 定义。To determine all possible values for an ENUM column, use SHOW COLUMNS FROM tbl_name LIKE 'enum_col' and parse the ENUM definition in the Type column of the output.

在 C API 中,ENUM 值以字符串形式返回。有关使用结果集元数据将它们与其他字符串区分的信息,请参见 C API 基本数据结构。In the C API, ENUM values are returned as strings. For information about using result set metadata to distinguish them from other strings, see C API Basic Data Structures.

空或 NULL 枚举值Empty or NULL Enumeration Values

在某些情况下,枚举值也可以是空字符串('')或 NULL:An enumeration value can also be the empty string ('') or NULL under certain circumstances:

  • 如果你向 ENUM 插入无效值(也就是说,不在允许值列表中的字符串),则会插入空字符串作为特殊错误值。这个字符串可以通过它的数值为 0 与“普通”的空字符串区分开来。有关枚举值的数值索引的详细信息,请参阅 枚举字面值的索引值。If you insert an invalid value into an ENUM (that is, a string not present in the list of permitted values), the empty string is inserted instead as a special error value. This string can be distinguished from a “normal” empty string by the fact that this string has the numeric value 0. See Index Values for Enumeration Literals for details about the numeric indexes for the enumeration values.

    如果启用了严格 SQL 模式,尝试插入无效的 ENUM 值将导致错误。If strict SQL mode is enabled, attempts to insert invalid ENUM values result in an error.

  • 如果一个 ENUM 列被声明允许 NULL,则 NULL 值对于该列是有效的,并且默认值为 NULL。如果一个 ENUM 列被声明为 NOT NULL,其默认值是允许值列表中的第一个元素。If an ENUM column is declared to permit NULL, the NULL value is a valid value for the column, and the default value is NULL. If an ENUM column is declared NOT NULL, its default value is the first element of the list of permitted values.

枚举排序Enumeration Sorting

ENUM 值根据它们的索引号进行排序,这些索引号取决于枚举成员在列规范中列出的顺序。例如,对于 ENUM('b', 'a'),'b' 排在 'a' 之前。空字符串排在非空字符串之前,而 NULL 值排在所有其他枚举值之前。ENUM values are sorted based on their index numbers, which depend on the order in which the enumeration members were listed in the column specification. For example, 'b' sorts before 'a' for ENUM('b', 'a'). The empty string sorts before nonempty strings, and NULL values sort before all other enumeration values.

为了在对 ENUM 列使用 ORDER BY 子句时防止出现意外结果,请使用以下技术之一:To prevent unexpected results when using the ORDER BY clause on an ENUM column, use one of these techniques:

  • 按字母顺序指定 ENUM 列表。Specify the ENUM list in alphabetic order.

  • 通过编写 ORDER BY CAST(col AS CHAR) 或 ORDER BY CONCAT(col),确保列按字典顺序而不是索引号排序。Make sure that the column is sorted lexically rather than by index number by coding ORDER BY CAST(col AS CHAR) or ORDER BY CONCAT(col).

枚举限制Enumeration Limitations

枚举值不能是表达式,即使该表达式计算结果为字符串值。An enumeration value cannot be an expression, even one that evaluates to a string value.

例如,这个 CREATE TABLE 语句 不能 工作,因为 CONCAT 函数不能用于构建枚举值:For example, this CREATE TABLE statement does not work because the CONCAT function cannot be used to construct an enumeration value:

CREATE TABLE sizes (
    size ENUM('small', CONCAT('med','ium'), 'large')
);

您也不能将用户变量用作枚举值。这对语句 不能 工作:You also cannot employ a user variable as an enumeration value. This pair of statements do not work:

SET @mysize = 'medium';

CREATE TABLE sizes (
    size ENUM('small', @mysize, 'large')
);

我们强烈建议您不要使用数字作为枚举值,因为与合适的TINYINT或SMALLINT类型相比,它并不能节省存储空间,而且如果您错误地引用ENUM值,很容易将字符串与底层数字值(可能不相同)混淆。如果确实使用数字作为枚举值,请始终用引号括起来。如果省略引号,数字将被视为索引。请参见枚举字面量的处理,了解即使是带引号的数字也可能被错误地用作数字索引值。We strongly recommend that you do not use numbers as enumeration values, because it does not save on storage over the appropriate TINYINT or SMALLINT type, and it is easy to mix up the strings and the underlying number values (which might not be the same) if you quote the ENUM values incorrectly. If you do use a number as an enumeration value, always enclose it in quotation marks. If the quotation marks are omitted, the number is regarded as an index. See Handling of Enumeration Literals to see how even a quoted number could be mistakenly used as a numeric index value.

定义中的重复值会导致警告,如果启用严格 SQL 模式则会导致错误。Duplicate values in the definition cause a warning, or an error if strict SQL mode is enabled.