### 11.3.5 枚举类型

[](<>)[](<>)

一个`枚举`是一个字符串对象，其值选自创建表时列规范中明确枚举的允许值列表。

看[第 11.3.1 节，“字符串数据类型语法”](string-type-syntax.html)为了[`枚举`](enum.html)类型语法和长度限制。

这[`枚举`](enum.html)类型具有以下优点：

-   在列具有一组有限的可能值的情况下压缩数据存储。您指定为输入值的字符串会自动编码为数字。看[第 11.7 节，“数据类型存储要求”](storage-requirements.html)对于存储要求`枚举`类型。

-   可读的查询和输出。这些数字被翻译回查询结果中的相应字符串。

    以及需要考虑的这些潜在问题：

-   如果您使枚举值看起来像数字，则很容易将文字值与其内部索引号混淆，如中所述[枚举限制](enum.html#enum-limits).

-   使用`枚举`中的列`订购方式`条款需要格外小心，如[枚举排序](enum.html#enum-sorting).

-   [创建和使用枚举列](enum.html#enum-using)

-   [枚举文字的索引值](enum.html#enum-indexes)

-   [枚举文本的处理](enum.html#enum-literals)

-   [枚举值为空或空](enum.html#enum-nulls)

-   [枚举排序](enum.html#enum-sorting)

-   [枚举限制](enum.html#enum-limits)

#### 创建和使用枚举列

枚举值必须是带引号的字符串文字。例如，可以使用`枚举`像这样的专栏：

```
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万行，值为`“中等”`将需要100万字节的存储空间，而如果存储实际字符串，则需要600万字节的存储空间`“中等”`在一个`瓦尔查尔`柱

#### 枚举文字的索引值

每个枚举值都有一个索引：

-   列规范中列出的元素被分配了索引号，从1开始。

-   空字符串错误值的索引值为0。这意味着您可以使用以下[`选择`](select.html)语句来查找无效的`枚举`分配的值为：

    ```
    mysql> SELECT * FROM tbl_name WHERE enum_col=0;
    ```

-   指数`无效的`价值是`无效的`.

-   这里的术语“索引”指的是枚举值列表中的一个位置。它与表索引无关。

    例如，指定为`枚举（“水星”、“金星”、“地球”）`可以具有此处显示的任何值。还显示了每个值的索引。

| 价值 | 指数 |
| --- | --- |
| `无效的` | `无效的` |
| `''` | 0 |
| `“水星”` | 1. |
| `“维纳斯”` | 2. |
| `“地球”` | 3. |

一[`枚举`](enum.html)列最多可以有65535个不同的元素。

如果你找到一个`枚举`值在数值上下文中，返回列值的索引。例如，可以从数据库中检索数值`枚举`像这样的专栏：

```
mysql> SELECT enum_col+0 FROM tbl_name;
```

功能，例如[`SUM（）`](aggregate-functions.html#function_sum)或[`平均值（）`](aggregate-functions.html#function_avg)如果需要的话，可以将参数转换为数字。对于`枚举`值，则在计算中使用索引号。

#### 枚举文本的处理

[](<>)

尾随空格将自动从中删除`枚举`创建表时，表定义中的成员值。

检索时，将值存储到`枚举`列使用列定义中使用的大写字母显示。注意`枚举`可以为列指定字符集和排序规则。对于二进制或区分大小写的排序规则，在为列赋值时会考虑字母大小写。

如果你把一个数字存储到`枚举`列中，该数字被视为可能值的索引，存储的值是具有该索引的枚举成员。（然而，这是事实。）*不*合作[`加载数据`](load-data.html)，将所有输入视为字符串。）如果数值被引用，如果枚举值列表中没有匹配的字符串，它仍然被解释为索引。由于这些原因，不建议定义`枚举`列的枚举值看起来像数字，因为这很容易让人困惑。例如，以下列包含字符串值为的枚举成员`'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       |
+---------+
```

确定`枚举`列，使用[`显示来自*`tbl\_名称`*就像*`enum_col`*'`](show-columns.html)然后分析`枚举`中的定义`类型`输出的列。

在C API中，`枚举`值作为字符串返回。有关使用结果集元数据将其与其他字符串区分开来的信息，请参阅[C API基本数据结构](https://dev.mysql.com/doc/c-api/8.0/en/c-api-data-structures.html).

#### 枚举值为空或空

枚举值也可以是空字符串(`''`)或者`无效的`在某些情况下：

-   如果将无效值插入`枚举`（即，允许值列表中不存在的字符串），空字符串将作为特殊错误值插入。此字符串与“普通”空字符串的区别在于，此字符串的数值为0。看见[枚举文字的索引值](enum.html#enum-indexes)有关枚举值的数字索引的详细信息。

    如果启用了严格SQL模式，则尝试插入无效`枚举`值会导致错误。

-   如果`枚举`列被声明为允许`无效的`这个`无效的`值是该列的有效值，默认值为`无效的`.如果`枚举`列已声明`非空`，其默认值是允许值列表的第一个元素。

#### 枚举排序

`枚举`值根据其索引编号进行排序，索引编号取决于枚举成员在列规范中列出的顺序。例如`“b”`排序之前`“a”`对于`枚举（'b'，'a'）`。空字符串在非空字符串之前排序，并且`无效的`值排序在所有其他枚举值之前。

以防止在使用`订购人`关于`枚举`列中，使用以下技术之一：

-   指定`枚举`按字母顺序列出。

-   确保该列按词汇排序，而不是按编码的索引号排序`按演员顺序(*`上校`*作为字符）`或`康卡特订购(*`上校`*)`.

#### 枚举限制

枚举值不能是表达式，甚至不能是计算结果为字符串值的表达式。

比如这个[`创建表格`](create-table.html)声明确实如此*不*工作是因为`海螺`函数不能用于构造枚举值：

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

也不能将用户变量用作枚举值。这两条语句*不*工作：

```
SET @mysize = 'medium';

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

我们强烈建议您这样做*不*使用数字作为枚举值，因为它不会通过适当的[`TINYINT`](integer-types.html)或[`斯莫林`](integer-types.html)输入，如果您引用`枚举`值不正确。如果确实使用数字作为枚举值，请始终用引号将其括起来。如果省略引号，则该数字被视为索引。看见[枚举文本的处理](enum.html#enum-literals)看看连带引号的数字都会被错误地用作数字索引值。

如果启用了严格SQL模式，定义中的重复值将导致警告或错误。
