11.3.6 SET 类型

SET是一个字符串对象,可以具有零个或多个值,每个值都必须从创建 table 时指定的允许值列 table 中选择。由多个集合成员组成的SET列值用用逗号(,)分隔的成员指定。这样的结果是SET成员值本身不应包含逗号。

例如,指定为SET('one', 'two') NOT NULL的列可以具有以下任何值:

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

SET列最多可包含 64 个不同的成员。在 table 的ENUMSET列中,一个 table 最多可以包含 255 个唯一元素列 table 定义。有关此限制的更多信息,请参见.frm 文件结构施加的限制

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

创建 table 时,会从 table 定义中的SET成员值中自动删除尾随空格。

有关SET类型的存储要求,请参见字符串类型存储要求

有关SET类型的语法和长度限制,请参见第 11.3.1 节“字符串数据类型语法”

检索到后,将使用列定义中使用的字母大小写显示存储在SET列中的值。请注意,可以为SET列分配一个字符集和排序规则。对于二进制或区分大小写的排序规则,在将值分配给列时要考虑字母大小写。

MySQL 以数字方式存储SET个值,其中存储值的低位对应于第一个 set 成员。如果在数字上下文中检索SET值,则检索到的值具有与组成列值的集合成员相对应的位集合。例如,您可以像这样从SET列中检索数值:

mysql> SELECT set_col+0 FROM tbl_name;

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

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

如果为该列分配值9,即二进制数1001,那么将选择第一个和第四个SET值成员'a''d',结果值为'a,d'

对于包含多个SET元素的值,插入该值时元素的列出 Sequences 无关紧要。给定元素在值中列出多少次也无关紧要。以后检索该值时,该值中的每个元素都会出现一次,并按照在创建 table 时指定它们的 Sequences 列出这些元素。假设将一列指定为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 成员的行。第二个相似但不相同:它查找行中_ set_col 包含 value *的行,甚至作为另一个 set 成员的子串。

也允许使用以下语句:

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

这些语句中的第一个语句查找包含第一个 set 成员的值。第二个寻找完全匹配。比较第二种类型时要小心。将设置值与'val1,val2'进行比较所返回的结果不同于将值与'val2,val1'进行比较所得出的结果。您应按照列定义中列出的 Sequences 指定值。

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

在 C API 中,SET值作为字符串返回。有关使用结果集元数据将它们与其他字符串区分开的信息,请参见第 27.7.4 节“ C API 数据结构”

首页