11.3.6 SET 类型
SET
是一个字符串对象,可以具有零个或多个值,每个值都必须从创建 table 时指定的允许值列 table 中选择。由多个集合成员组成的SET
列值用用逗号(,
)分隔的成员指定。这样的结果是SET
成员值本身不应包含逗号。
例如,指定为SET('one', 'two') NOT NULL
的列可以具有以下任何值:
''
'one'
'two'
'one,two'
SET列最多可包含 64 个不同的成员。在 table 的ENUM和SET列中,一个 table 最多可以包含 255 个唯一元素列 table 定义。有关此限制的更多信息,请参见.frm 文件结构施加的限制。
定义中的重复值会导致警告,如果启用了严格的 SQL 模式,则会导致错误。
创建 table 时,会从 table 定义中的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 数据结构”。