对于“enum”和“set”的 MySQL 数据类型,使用一个与另一个有什么区别和优缺点?
示例数据类型:
- 枚举('A','B','C')
- 设置('A','B','C')
我知道的唯一区别是 ENUM 只允许选择一个值,而 SET 允许选择多个值。
类比:
ENUM = 单选字段(仅接受的值是列出的值,只能选择一个)
SET = 复选框字段(仅接受的值是列出的值,可以选择多个)
As the MySQL documentation states:
Definition of a ENUM or SET column does act as a constraint on values entered into the column. An error occurs for values that do not satisfy these conditions:
An ENUM value must be one of those listed in the column definition, or the internal numeric equivalent thereof. The value cannot be the error value (that is, 0 or the empty string). For a column defined as ENUM('a','b','c'), values such as '', 'd', or 'ax' are illegal and are rejected.
A SET value must be the empty string or a value consisting only of the values listed in the column definition separated by commas. For a column defined as SET('a','b','c'), values such as 'd' or 'a,b,c,d' are illegal and are rejected.
Enum 和 Set 完全取决于要求,例如,如果您有一个单选按钮列表,一次只能选择一个,请使用 Enum。如果您有一个复选框列表,一次可以选择一个以上的项目,请使用 set。
CREATE TABLE setTest(
attrib SET('bold','italic','underline')
);
INSERT INTO setTest (attrib) VALUES ('bold');
INSERT INTO setTest (attrib) VALUES ('bold,italic');
INSERT INTO setTest (attrib) VALUES ('bold,italic,underline');
你可以把上面的代码复制粘贴到mysql中,你会发现SET其实是一个集合。您可以存储您声明的每个属性组合。
CREATE TABLE enumTest(
color ENUM('red','green','blue')
);
INSERT INTO enumTest (color) VALUES ('red');
INSERT INTO enumTest (color) VALUES ('gray');
INSERT INTO enumTest (color) VALUES ('red,green');
您也可以复制上面的代码。而且你会发现每个ENUM实际上每次只能存储一次。你会发现最后两行的结果都是空的。
其实很简单:
当您定义ENUM('Yes', 'No', 'Maybe')时,您必须仅插入这些值之一(或它们的位置索引号)
当您定义SET('R', 'W', 'X')时,您可以插入一个空字符串,或者这些值中的一个或多个。如果您插入不在预定义集中的内容,则会插入一个空字符串。请注意,在插入所有重复值之前,都会丢弃所有重复值,因此只插入每个允许值的一个实例。
希望这可以清除它。
请注意,Winbobob 的答案是不正确的,并且包含有缺陷的示例,因为插入多个值时,值必须是字符串,用逗号分隔。他所有的插入实际上只插入一个值(最后两个不在定义的集合中)
ENUM --> 只选择一个可用的值来插入。
(no_null, no_any_duplicate)
SET --> 选择任何组合或单个值,如集合并将它们插入。
(null, individual_values, all_the_available_values_together)
我补充了到目前为止答案中已经提到的几点,因为我在差异上添加了一个额外的点 -
MySQL 在内部将 ENUM 字符串值存储为值 1 到 n 的十进制整数,用于枚举中具有 n 个成员的列。
MySQL 将 SET 字符串值表示为一个位图,每个值使用一位,因此这些值在内部存储为 1、2、4、8、..... 最多 65,535 个,最多 64 个成员。
这一点证明如下——
枚举示例 -
我创建具有数据类型的table1
列的表,具有以下表结构 -col1
ENUM('a','b','c','d','e','f','g','h','i','j')
| table1 | CREATE TABLE `table1` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`col1` enum('a','b','c','d','e','f','g','h','i','j') DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
col1
内部存储如下 -
+----+---------+---------------+
| id | element | decimal_value |
+----+---------+---------------+
| 1 | a | 1 |
| 2 | b | 2 |
| 3 | c | 3 |
| 4 | d | 4 |
| 5 | e | 5 |
| 6 | f | 6 |
| 7 | g | 7 |
| 8 | h | 8 |
| 9 | i | 9 |
| 10 | j | 10 |
+----+---------+---------------+
现在,假设我们要将值 -'e'
插入col1
'e'
有索引5
因此要进入'e'
我们col1
使用以下查询 -
INSERT INTO table1 VALUES (1, 5);
然后我们检查存在于table1
-
SELECT * FROM table1;
+----+------+
| id | col1 |
+----+------+
| 1 | e |
+----+------+
我们看到在第一行我们的值为col1
as'e'
同样,假设我们想将值 -'i'
插入col1
'i'
有索引9
因此要进入'i'
我们col1
使用以下查询 -
INSERT INTO table1 VALUES (2, 9);
然后我们检查存在于table1
-
SELECT * FROM table1;
+----+------+
| id | col1 |
+----+------+
| 1 | e |
| 2 | i |
+----+------+
我们看到在第二行我们的值为col1
as'i'
同样,假设我们想将值 -'a'
插入col1
'a'
有索引1
因此要进入'a'
我们col1
使用以下查询 -
INSERT INTO table1 VALUES (3, 1);
然后我们检查存在于table1
-
SELECT * FROM table1;
+----+------+
| id | col1 |
+----+------+
| 1 | e |
| 2 | i |
| 3 | a |
+----+------+
我们看到在第三行我们的值为col1
as'a'
设置示例 -
我创建具有数据类型的table1
列的表,具有以下表结构 -col1
SET('a','b','c','d','e','f','g','h','i','j')
| table1 | CREATE TABLE `table1` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`col1` set('a','b','c','d','e','f','g','h','i','j') DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
col1
内部存储如下 -
+----+---------+----------------+---------------+
| id | element | binary_value | decimal_value |
+----+---------+----------------+---------------+
| 1 | a | 0000 0000 0001 | 1 |
| 2 | b | 0000 0000 0010 | 2 |
| 3 | c | 0000 0000 0100 | 4 |
| 4 | d | 0000 0000 1000 | 8 |
| 5 | e | 0000 0001 0000 | 16 |
| 6 | f | 0000 0010 0000 | 32 |
| 7 | g | 0000 0100 0000 | 64 |
| 8 | h | 0000 1000 0000 | 128 |
| 9 | i | 0001 0000 0000 | 256 |
| 10 | j | 0010 0000 0000 | 512 |
+----+---------+----------------+---------------+
现在,假设我们要将值 -'e,f,i'
插入col1
然后'e,f,i'
通过将 的 binary_values 相加来计算 binary_value 'e'
,'f'
并且'i'
对应的0001 0011 0000
decimal_value304
如下所示 -
+----+---------+----------------+---------------+
| id | element | binary_value | decimal_value |
+----+---------+----------------+---------------+
| 5 | e | 0000 0001 0000 | 16 |
| 6 | f | 0000 0010 0000 | 32 |
| 9 | i | 0001 0000 0000 | 256 |
+----+---------+----------------+---------------+
| | e,f,i | 0001 0011 0000 | 304 |
+----+---------+----------------+---------------+
因此要进入'e,f,i'
我们col1
使用以下查询 -
INSERT INTO table1 VALUES (1, 304);
然后我们检查存在于table1
-
SELECT * FROM table1;
+----+-------+
| id | col1 |
+----+-------+
| 1 | e,f,i |
+----+-------+
我们看到在第一行我们的值为col1
as'e,f,i'
同样,假设我们想将值 -'a,j'
插入col1
然后binary_value'a,j'
是通过将binary_values'a'
与'j'
is相加来计算的0010 0000 0001
,对应的decimal_value513
如下图所示——
+----+---------+----------------+---------------+
| id | element | binary_value | decimal_value |
+----+---------+----------------+---------------+
| 1 | a | 0000 0000 0001 | 1 |
| 10 | j | 0010 0000 0000 | 512 |
+----+---------+----------------+---------------+
| | a,j | 0010 0000 0001 | 513 |
+----+---------+----------------+---------------+
因此要进入'a,j'
我们col1
使用以下查询 -
INSERT INTO table1 VALUES (2, 513);
然后我们检查存在于table1
-
SELECT * FROM table1;
+----+-------+
| id | col1 |
+----+-------+
| 1 | e,f,i |
| 2 | a,j |
+----+-------+
我们看到在第二行我们的值为col1
as'a,j'
同样,假设我们想将值 -'b,d,h,i'
插入col1
然后的 binary_value是通过将,的'b,d,h,i'
binary_values 相加计算得到的,'b'
对应的decimal_value如下所示'd'
'h'
'i'
0001 1000 1010
394
+----+---------+----------------+---------------+
| id | element | binary_value | decimal_value |
+----+---------+----------------+---------------+
| 2 | b | 0000 0000 0010 | 2 |
| 4 | d | 0000 0000 1000 | 8 |
| 8 | h | 0000 1000 0000 | 128 |
| 9 | i | 0001 0000 0000 | 256 |
+----+---------+----------------+---------------+
| | b,d,h,i | 0001 1000 1010 | 394 |
+----+---------+----------------+---------------+
因此要进入'b,d,h,i'
我们col1
使用以下查询 -
INSERT INTO table1 VALUES (3, 394);
然后我们检查存在于table1
-
SELECT * FROM table1;
+----+---------+
| id | col1 |
+----+---------+
| 1 | e,f,i |
| 2 | a,j |
| 3 | b,d,h,i |
+----+---------+
我们看到在第三行我们的值为col1
as'b,d,h,i'