Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  The SET Type

13.3.6 SET 类型

SET 是一个字符串对象,可以有零个或多个值,每个值都必须来自于在表创建时指定的允许值列表。 SET 列值,如果包含多个成员,使用逗号(,)分隔。由于这个原因,SET 成员值不能包含逗号。

例如,一列指定为 SET('one', 'two') NOT NULL 可以有以下这些值:

''
'one'
'two'
'one,two'

一个 SET 列最多可以有 64 个不同的成员。

在定义中出现重复值将导致警告,或者在启用严格 SQL 模式时报错。

在创建表时,SET 成员值中的尾部空格将自动删除。

查看字符串类型存储要求以获取 SET 类型的存储要求。

查看第13.3.1节,“字符串数据类型语法”以获取 SET 类型的语法和长度限制。

当从 SET 列中检索值时,值将使用列定义中的字母大小写。注意 SET 列可以指定字符集和排序规则。对于二进制或区分大小写的排序规则,字母大小写将在将值分配给列时被考虑。

MySQL 将 SET 值存储为数字,存储值的低位对应于列值中的第一个成员。如果您在数值上下文中检索 SET 值,检索到的值将具有与列值中的成员相对应的位设置。例如,可以像这样从 SET 列中检索数字值:

mysql> SELECT set_col+0 FROM tbl_name;

如果将数字存储到 SET 列中,存储值的位将确定列值中的成员。例如,对于指定为 SET('a','b','c','d') 的列,成员具有以下十进制和二进制值。

SET Member Decimal Value Binary Value
'a' 1 0001
'b' 2 0010
'c' 4 0100
'd' 8 1000

如果将值 9 分配给该列,那么该值在二进制中为 1001,因此第一个和第四个 SET 值成员 'a''d' 将被选择,结果值为 'a,d'

对于包含多个SET元素的值,它不管元素的顺序是什么时候插入的,也不管同一个元素被列出多少次。当将值检索时,每个元素都只出现一次,元素的顺序与在表创建时指定的顺序相同。假设一个列被指定为SET('a','b','c','d'):

mysql> CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));

如果你插入值'a,d', 'd,a', 'a,d,d', 'a,d,a''d,a,d'

mysql> INSERT INTO myset (col) VALUES 
-> ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

然后,这些值都将被检索为'a,d'

mysql> SELECT col FROM myset;
+------+
| col  |
+------+
| a,d  |
| a,d  |
| a,d  |
| a,d  |
| a,d  |
+------+
5 rows in set (0.04 sec)

如果你将SET列设置为无效值,该值将被忽略,并且将发出警告:

mysql> INSERT INTO myset (col) VALUES ('a,d,d,s');
Query OK, 1 row affected, 1 warning (0.03 sec)

mysql> SHOW WARNINGS;
+---------+------+------------------------------------------+
| Level   | Code | Message                                  |
+---------+------+------------------------------------------+
| Warning | 1265 | Data truncated for column 'col' at row 1 |
+---------+------+------------------------------------------+
1 row in set (0.04 sec)

mysql> SELECT col FROM myset;
+------+
| col  |
+------+
| a,d  |
| a,d  |
| a,d  |
| a,d  |
| a,d  |
| a,d  |
+------+
6 rows in set (0.01 sec)

如果启用严格SQL模式,尝试插入无效SET值将导致错误:

SET值将按数字排序。NULL值将在非NULL SET值之前排序。

函数,如SUM()AVG(),期望数字参数将对参数进行转换。如果SET值,则转换操作将使用数字值:

通常,你使用FIND_IN_SET()函数或LIKE操作来搜索SET值:

mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;
mysql> SELECT * FROM tbl_name WHERE set_col LIKE '%value%';

第一个语句找到set_col包含value成员的行。第二个语句类似,但不是同一个:它找到set_col包含value的任何地方,即使是另一个成员的子串。

以下语句也被允许:

mysql> SELECT * FROM tbl_name WHERE set_col & 1;
mysql> SELECT * FROM tbl_name WHERE set_col = 'val1,val2';

第一个语句查找包含第一个成员的值。第二个语句查找exact match。请注意,比较第二种类型的结果将不同于比较第二种类型的结果。比较值到'val1,val2'将返回不同的结果,而不是比较值到'val2,val1'。你应该将值指定为列定义中指定的顺序。

要确定SET列的所有可能值,请使用SHOW COLUMNS FROM tbl_name LIKE set_col并解析SET定义在输出的Type列中。

在C API中,SET值将作为字符串返回。关于使用结果集元数据来区分它们的信息,请见C API Basic Data Structures