ITPub博客

首页 > 数据库 > > 11.3 字符串类型

11.3 字符串类型

作者:飘絮絮絮丶 时间:2020-05-12 10:35:17 0 删除 编辑

参考官方文档:

dev.mysql.com/doc/refma



字符串类型是CHAR,VARCHAR,BINARY,VARBINARY,BLOB,TEXT,ENUM和SET。


MySQL以字符单位解释字符列定义中的长度规范。 这适用于CHAR,VARCHAR和TEXT类型。


许多字符串数据类型的列定义可以包含指定字符集或列的排序规则的属性。 这些属性适用于CHAR,VARCHAR,TEXT类型,ENUM和SET数据类型:

  • CHARACTER SET属性指定字符集,COLLATE属性指定字符集的排序规则。 例如:

CREATE TABLE t ( c1 VARCHAR(20) CHARACTER SET utf8, c2 TEXT CHARACTER SET latin1 COLLATE latin1_general_cs );


此表定义创建一个名为c1的列,该列具有一个字符集utf8,该字符集具有默认排序规则,名为c2的列具有latin1字符集和区分大小写的排序规则。


CHARSET是CHARACTER SET的同义词。


  • 为字符串数据类型指定CHARACTER SET binary 属性会导致将该列创建为相应的二进制字符串数据类型:CHAR变为BINARY,VARCHAR变为VARBINARY,TEXT变为BLOB。 对于ENUM和SET数据类型,这不会发生; 它们按照声明被创建。 假设你使用下列定义来指定一个表:


CREATE TABLE t ( c1 VARCHAR(10) CHARACTER SET binary, c2 TEXT CHARACTER SET binary, c3 ENUM('a','b','c') CHARACTER SET binary );


结果表有这样的定义:


CREATE TABLE t ( c1 VARBINARY(10), c2 BLOB, c3 ENUM('a','b','c') CHARACTER SET binary );

  • BINARY属性是指定表格默认字符集和该字符集的二进制(_bin)排序规则的简写。 在这种情况下,比较和排序基于数字字符代码值。
  • ASCII属性是CHARACTER SET latin1的简写
  • UNICODE属性是CHARACTER SET ucs2的简写。


字符列比较和排序基于分配给列的排序规则。 对于CHAR,VARCHAR,TEXT,ENUM和SET数据类型,可以使用 binary (_bin)排序规则或BINARY属性声明列,以使比较和排序使用基础字符代码值而不是词法排序。


  • [NATIONAL] CHAR[(M)] [CHARACTER SETcharset_name] [COLLATE collation_name]


一个固定长度的字符串,在存储时总是用空格填充指定的长度。 M代表字符中的列长度。 M的范围是0到255.如果省略M,则长度为1。


注意:

除非启用PAD_CHAR_TO_FULL_LENGTH SQL模式,否则在检索CHAR值时删除尾随空格。


CHAR是CHARACTER的简写。 NATIONAL CHAR(或其等效缩写形式,NCHAR)是定义CHAR列应使用某些预定义字符集的标准SQL方法。 MySQL使用utf8作为这个预定义的字符集。


CHAR BYTE数据类型是BINARY数据类型的别名。 这是一个兼容性功能。


MySQL允许你创建一个类型为CHAR(0)的列。 当您必须符合依赖列的存在但实际上并未使用其值的旧应用程序时,这非常有用。 当您需要只能取两个值的列时,CHAR(0)也相当不错:定义为CHAR(0)NULL的列只占用一位,并且只能取值NULL和''(空字符串)。

  • [NATIONAL] VARCHAR(M) [CHARACTER SETcharset_name] [COLLATE collation_name]


一个可变长度的字符串。 M代表字符中的最大列长度。 M的范围是0到65,535。 VARCHAR的有效最大长度取决于最大行大小(65,535字节,在所有列中共享)和使用的字符集。 例如,utf8字符每个字符最多可能需要三个字节,因此使用utf8字符集的VARCHAR列可以声明为最多21,844个字符。


MySQL将VARCHAR值存储为1字节或2字节长度的前缀和数据。 长度前缀表示该值中的字节数。 如果值不超过255个字节,则VARCHAR列使用一个长度字节,如果值可能需要超过255个字节,则使用两个长度字节。


注意:

MySQL遵循标准的SQL规范,并且不会从VARCHAR值中删除尾随空格。


VARCHAR是CHARACTER VARYING的简写。 NATIONAL VARCHAR是定义VARCHAR列应使用某些预定义字符集的标准SQL方式。 MySQL使用utf8作为这个预定义的字符集。 第10.3.7节“国家字符集”。 NVARCHAR是NATIONAL VARCHAR的缩写。


  • BINARY[(M)]


BINARY类型与CHAR类型相似,但存储二进制字节字符串而不是非二进制字符串。 可选长度M表示以字节为单位的列长度。 如果省略,M默认为1。

  • VARBINARY(M)


VARBINARY类型与VARCHAR类型相似,但存储二进制字节字符串而不是非二进制字符串。 M表示以字节为单位的最大列长度。

  • TINYBLOB


最大长度为255个字节的BLOB列。 每个TINYBLOB值都使用一个1字节长度的前缀进行存储该值中的字节数。


  • TINYTEXT [CHARACTER SET charset_name] [COLLATE collation_name]


最大长度为255个字符的TEXT列。 如果值包含多字节字符,则有效最大长度会减少。 每个TINYTEXT值都使用一个1字节长度的前缀进行存储该值中的字节数。


  • BLOB[(M)]

最大长度为65,535字节的BLOB列。 每个BLOB值都使用一个2字节长度前缀进行存储该值中的字节数。


可以给这个类型一个可选的长度M. 如果这样做了,MySQL创建列作为最大的BLOB类型,其大小足以保存长度为M字节的值。


最大长度为65,535个字符的TEXT列。 如果值包含多字节字符,则有效最大长度会减少。 每个TEXT值都使用一个2字节的长度前缀进行存储该值中的字节数。


可以给这个类型一个可选的长度M. 如果这样做了,MySQL将创建列作为最大的TEXT类型,其大小足以保存长度为M个字符的值。


  • MEDIUMBLOB

最大长度为16,777,215 个字节的BLOB列。 每个MEDIUMBLOB值都使用一个3字节的长度前缀进行存储该值中的字节数。


  • MEDIUMTEXT [CHARACTER SET charset_name] [COLLATE collation_name]


一个TEXT列,最大长度为16,777,215 个字符。 如果值包含多字节字符,则有效最大长度会减少。 每个MEDIUMTEXT值都使用一个3字节的长度前缀进行存储该值中的字节数。

  • LONGBLOB

一个BLOB列,最大长度为4,294,967,295或4GB个字节。 LONGBLOB列的有效最大长度取决于客户端/服务器协议和可用内存中配置的最大数据包大小。 每个LONGBLOB值都使用一个4字节长度前缀进行存储该值中的字节数。


  • LONGTEXT [CHARACTER SET charset_name] [COLLATE collation_name]


一个TEXT列,最大长度为4,294,967,295或4GB个字符。 如果值包含多字节字符,则有效最大长度会减少。 LONGTEXT列的有效最大长度还取决于客户端/服务器协议和可用内存中配置的最大数据包大小。 每个LONGTEXT值都使用一个4字节的长度前缀进行存储该值中的字节数。


  • ENUM('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name]


枚举。 一个字符串对象,只能有一个值,从值列表值'value1','value2',...,NULL或特殊的'' 错误值中选择。 ENUM值在内部表示为整数。

ENUM列最多可以包含65,535个不同的元素。 (实际限制为小于3000.)一个表的ENUM和SET列中的唯一元素列表定义被视为一个组。

  • SET('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name]


集合。 一个字符串对象,可以有零个或多个值,每个值都必须从值'value1','value2'列表中选择,SET值在内部表示为整数。


SET列最多可以有64个不同的成员。 一个表在ENUM和SET列中可以有不超过255个唯一元素列表定义,并被视为一个组。






11.4.1 CHAR 和 VARCHAR 类型


CHAR和VARCHAR类型相似,但在存储和检索方式上有所不同。 它们的最大长度和尾部空格是否保留也不同。


CHAR和VARCHAR类型声明的长度指示要存储的最大字符数。 例如,CHAR(30)最多可以容纳30个字符。


CHAR列的长度固定为您在创建表时声明的长度。 长度可以是0到255之间的任何值。当存储CHAR值时,它们用空格填充到指定的长度。 当检索到CHAR值时,除非启用了PAD_CHAR_TO_FULL_LENGTH SQL模式,否则将删除尾随空格。


VARCHAR列中的值是可变长度的字符串。 长度可以指定为0到65,535之间的值。 VARCHAR的有效最大长度取决于最大行大小(65,535字节,在所有列中共享)和使用的字符集。


与CHAR相反,VARCHAR值存储为1字节或2字节长度前缀加数据。 长度前缀表示该值中的字节数。 如果值不超过255个字节,则列使用一个长度字节,如果值可能需要超过255个字节,则使用两个长度字节。


如果严格SQL模式未启用,并且将值分配给超过列最大长度的CHAR或VARCHAR列,则该值将被截断以生成警告。 要截断非空格字符,可以导致发生错误(而不是警告),并通过使用严格SQL模式来禁止插入值。


对于VARCHAR列,超过列长度的尾随空格在插入之前会被截断并生成警告,无论使用的是哪种SQL模式。 对于CHAR列,无论SQL模式如何,都会以无提示方式从插入的值中截断多余的尾随空格。


VARCHAR值在存储时不会被填充。 根据标准SQL存储和检索值时将保留尾随空格。


下表通过显示将各种字符串值存储到CHAR(4)和VARCHAR(4)列(假定列使用单字节字符集(如latin1))的结果来说明CHAR和VARCHAR之间的区别。




上述显示为存储在表最后一行的值仅适用于不使用严格模式的情况; 如果MySQL在严格模式下运行,超出列长度的值将不会被存储,并会导致错误。



InnoDB将长度大于或等于768字节的固定长度字段编码为可变长度字段,这些字段可以存储在页外。 例如,如果字符集的最大字节长度大于3,CHAR(255)列可能会超过768个字节,与utf8mb4一样。


如果将给定值存储到CHAR(4)和VARCHAR(4)列中,则从列中检索的值不总是相同,因为在检索时删除CHAR列中的尾随空格。 以下示例说明了这种差异:


mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4));

Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO vc VALUES ('ab ', 'ab ');

Query OK, 1 row affected (0.00 sec)

mysql> SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;

+---------------------+---------------------+

| CONCAT('(', v, ')') | CONCAT('(', c, ')') |

+---------------------+---------------------+

| (ab ) | (ab) |

+---------------------+---------------------+

1 row in set (0.06 sec)



根据分配给列的字符集排序规则对CHAR和VARCHAR列中的值进行排序和比较。



所有MySQL排序规则都是PAD SPACE类型。 这意味着所有CHAR,VARCHAR和TEXT值都会进行比较,而不考虑任何尾随空格。 在此上下文中的“比较”不包括LIKE模式匹配运算符,其尾部空格是重要的。 例如:


mysql> CREATE TABLE names (myname CHAR(10));

Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO names VALUES ('Monty');

Query OK, 1 row affected (0.00 sec)

mysql> SELECT myname = 'Monty', myname = 'Monty ' FROM names;

+------------------+--------------------+

| myname = 'Monty' | myname = 'Monty ' |

+------------------+--------------------+

| 1 | 1 |

+------------------+--------------------+

1 row in set (0.00 sec)

mysql> SELECT myname LIKE 'Monty', myname LIKE 'Monty ' FROM names;

+---------------------+-----------------------+

| myname LIKE 'Monty' | myname LIKE 'Monty ' |

+---------------------+-----------------------+

| 1 | 0 |

+---------------------+-----------------------+

1 row in set (0.00 sec)


对于所有MySQL版本都是如此,并且不受服务器SQL模式的影响。


对于尾随填充字符被去除或比较忽略它们的情况,如果列的索引需要唯一值,则插入到仅与尾部填充字符数不同的列值中将导致重复键错误。 例如,如果一个表包含'a',则尝试存储'a '会导致重复键错误。


--这种情况就需要应用上传递的时候去掉空格了。


11.4.2 BINARY 和 VARBINARY 类型



--用的好像比较少

除了包含二进制字符串而非非二进制字符串外,BINARY和VARBINARY类型与CHAR和VARCHAR类似。 也就是说,它们包含字节串而不是字符串。 这意味着它们具有二进制字符集和归类,并且比较和排序基于值中字节的数值。


对于BINARY和VARBINARY,允许的最大长度与CHAR和VARCHAR相同,除了BINARY和VARBINARY的长度是以字节为单位的长度而不是字符长度。


BINARY和VARBINARY数据类型与CHAR BINARY和VARCHAR BINARY数据类型不同。 对于后者类型,BINARY属性不会导致该列被视为二进制字符串列。 相反,它会导致使用列字符集的二进制(_bin)排序类型,而列本身包含非二进制字符串而不是二进制字节字符串。 例如,假定默认字符集是latin1,则CHAR(5)BINARY被视为CHAR(5)CHARACTER SET latin1 COLLATE latin1_bin。 这与BINARY(5)不同,后者存储具有二进制字符集和排序规则的5字节二进制字符串。



当存储BINARY值时,它们将填充值填充到指定的长度。 填充值是0x00(零字节)。 插入时值为右侧填充0x00,并且选择时不会删除结尾字节。 所有字节在比较中都很重要,包括ORDER BY和DISTINCT操作。 0x00字节和空格在比较中不同,0x00 <空格。



对于VARBINARY,插入时没有填充,并且在select时没有字节被删除。 所有字节在比较中都很重要,包括ORDER BY和DISTINCT操作。 0x00字节和空格在比较中不同,0x00 <空格。



对于那些尾部填充字节被剥离或比较忽略它们的情况,如果列的索引需要唯一值,则插入列值仅在尾部填充字节数上不同的值将导致重复键错误。 例如,如果一个表包含'a',则尝试存储'a \ 0'会导致重复键错误。



如果您计划使用BINARY数据类型来存储二进制数据,并且您要求检索到的值与存储的值完全相同,那么您应该仔细考虑前面的填充和清除特征。 以下示例说明了BINARY值的0x00填充如何影响列值比较:



mysql> CREATE TABLE t (c BINARY(3)); Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO t SET c = 'a'; Query OK, 1 row affected (0.01 sec)

mysql> SELECT HEX(c), c = 'a', c = 'a\0\0' from t;

+--------+---------+-------------+

| HEX(c) | c = 'a' | c = 'a\0\0' |

+--------+---------+-------------+

| 610000 | 0 | 1 |

+--------+---------+-------------+

1 row in set (0.09 sec)



如果检索的值必须与不带填充的存储指定的值相同,则最好使用VARBINARY或其中一种BLOB数据类型。





11.4.3 BLOB 和 TEXT 类型



BLOB是一个二进制大对象,可以容纳可变数量的数据。 四种BLOB类型是TINYBLOB,BLOB,MEDIUMBLOB和LONGBLOB。 这些不同仅在于它们可以容纳的值的最大长度。 四种TEXT类型是TINYTEXT,TEXT,MEDIUMTEXT和LONGTEXT。 这些对应于四种BLOB类型,并具有相同的最大长度和存储要求。


BLOB值被视为二进制字符串(字节字符串)。 它们具有二进制字符集和排序规则,并且比较和排序基于列值中字节的数值。 TEXT值被视为非二进制字符串(字符串)。 它们具有二进制以外的字符集,并且根据字符集的排序规则对值进行排序和比较。


如果严格SQL模式未启用,并且您将值分配给超过列最大长度的BLOB或TEXT列,则该值将被截断以生成警告。 要截断非空格字符,可以导致发生错误(而不是警告),并通过使用严格SQL模式来禁止插入值。



无论SQL模式如何,从要插入TEXT列的值中截断多余的尾随空格都会生成警告。


对于TEXT和BLOB列,在插入时没有填充,在选择时没有字节被去除。


如果对TEXT列进行索引,则索引条目比较将在末尾进行空格填充。 这意味着,如果索引需要唯一值,那么对于仅在尾部空格数量方面不同的值将出现重复键错误。 例如,如果一个表包含'a',则尝试存储'a '会导致重复键错误。 对于BLOB列来说这不是真的。

在大多数情况下,您可以将BLOB列视为VARBINARY列,可以尽可能大。 同样,您可以将TEXT列视为VARCHAR列。 BLOB和TEXT与VARBINARY和VARCHAR的区别在于:

  • 对于BLOB和TEXT列上的索引,您必须指定一个索引前缀长度。 对于CHAR和VARCHAR,前缀长度是可选的。
  • BLOB和TEXT列不能有DEFAULT值。


如果对TEXT数据类型使用BINARY属性,则该列将被分配列字符集的二进制(_bin)排序规则。


LONG和LONG VARCHAR映射到MEDIUMTEXT数据类型。 这是一个兼容性功能。


MySQL连接器/ ODBC将BLOB值定义为LONGVARBINARY和TEXT值作为LONGVARCHAR。

由于BLOB和TEXT值可能非常长,因此在使用它们时可能会遇到一些限制:


  • 字段排序时仅使用第一个max_sort_length字节。 max_sort_length的缺省值为1024.通过在服务器启动或运行时增加max_sort_length的值,可以在排序或分组中增加更多字节。 任何客户端都可以更改其会话max_sort_length变量的值:


mysql> SET max_sort_length = 2000;

mysql> SELECT id, comment FROM t -> ORDER BY comment;


  • 使用临时表处理的查询结果中的BLOB或TEXT列实例会导致服务器在磁盘而不是内存中使用表,因为MEMORY存储引擎不支持这些数据类型(请参见第8.4.4节“ “在MySQL中使用内部临时表”)。 使用磁盘会导致性能损失,因此只有在确实需要时才在查询结果中包含BLOB或TEXT列。 例如,避免使用SELECT *来选择所有列。
  • BLOB或TEXT对象的最大大小由其类型决定,但实际可在客户端和服务器之间传输的最大值取决于可用内存量和通信缓冲区的大小。 您可以通过更改max_allowed_packet变量的值来更改消息缓冲区大小,但您必须对服务器和客户端程序都这样做。 例如,mysql和mysqldump都可以让你改变客户端的max_allowed_packet值。 请参见第5.1.1节“配置服务器”,第4.5.1节“mysql - MySQL命令行工具”和第4.5.4节“mysqldump - 数据库备份程序”。 您可能还想要将存储的数据对象的数据包大小和大小与存储需求进行比较,请参见第11.8节“数据类型存储要求”


每个BLOB或TEXT值由一个单独分配的对象内部表示。 这与所有其他数据类型形成对比,在打开表格时,每个列会为其分配一次存储空间。


在某些情况下,可能需要将诸如媒体文件等二进制数据存储在BLOB或TEXT列中。 你可能会发现MySQL的字符串处理函数对于处理这些数据很有用。 请参见第12.5节“字符串函数”。 出于安全性和其他原因,通常最好使用应用程序代码而不是给予应用程序用户FILE权限。 您可以在MySQL论坛(forums.mysql.com/)中讨论各种语言和平台的具体情况。




11.4.4 ENUM 类型



ENUM是一个字符串对象,其值从列创建时在列定义中的明确枚举的允许值列表中选择。 它具有以下优点:



  • 紧凑型数据存储在列中的可能值有限的情况下。 您指定为输入值的字符串会自动编码为数字。 有关ENUM类型的存储要求,请参见第11.8节“数据类型存储要求”。
  • 可读的查询和输出。 这些数字将被转换回查询结果中的相应字符串。



创建和使用 ENUM 字段



枚举值必须是带引号的字符串。 例如,您可以创建一个ENUM列,如下所示:



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;



如果将实际字符串'medium'存储在VARCHAR列中,那么将100万行插入此表中的值为'medium'将需要100万字节的存储空间,而不是600万字节。


枚举文字的索引值



每个枚举值都有一个"索引":


  • 列说明中列出的元素分配索引编号,从1开始。
  • 空字符串错误值的索引值为0.这意味着您可以使用以下SELECT语句查找分配了无效ENUM值的行:


mysql> SELECT * FROM tbl_name WHERE enum_col=0;

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


例如,指定为ENUM('Mercury','Venus','Earth')的列可以具有此处显示的任何值。 还显示了每个值的索引。



ENUM列最多可以包含65,535个不同的元素。 (实际限制小于3000.)一个表在其ENUM和SET列中可以有不多于255个唯一元素列表定义,被视为一个组。



如果您在数字上下文中检索ENUM值,则返回列值的索引。 例如,您可以像这样从ENUM列中检索数值:



mysql> SELECT enum_col+0 FROM tbl_name;



SUM()或AVG()等需要数值参数的函数将参数转换为数字。 对于ENUM值,计算中使用索引编号。



枚举文字的处理



创建表时,尾部空格会自动从表定义中的ENUM成员值中删除。



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



如果将数字存储到ENUM列中,则该数字将被视为可能值的索引,并且存储的值是具有该索引的枚举成员。 (但是,这对LOAD DATA不起作用,LOAD DATA将所有输入视为字符串。)如果数字值被引用,如果枚举值列表中没有匹配的字符串,则仍将其解释为索引。 由于这些原因,建议使用枚举值看起来像数字的ENUM列是不可取的,因为这很容易造成混淆。 例如,以下列的枚举成员的字符串值为'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 |

+---------+



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




空或NULL枚举值

在某些情况下,枚举值也可以是空字符串('')或NULL:


  • 如果向ENUM中插入了无效值(即,允许值列表中不存在的字符串),则将插入空字符串作为特殊错误值。 该字符串可以与“普通”空字符串区分开来,因为该字符串的数值为0.有关枚举值的数字索引的详细信息,请参见枚举文字的索引值。


如果启用严格的SQL模式,则尝试插入无效的ENUM值会导致错误。


  • 如果ENUM列被声明为允许NULL,则NULL值是该列的有效值,并且默认值为NULL。 如果ENUM列被声明为NOT NULL,则其默认值是允许值列表中的第一个元素。


枚举排序

ENUM值根据它们的索引号进行排序,这取决于枚举成员在列定义中列出的顺序。 例如,对于ENUM('b','a'),'b'在'a'之前排序。 空字符串在非空字符串之前排序,而NULL值在所有其他枚举值之前排序。



为防止在ENUM列上使用ORDER BY子句时出现意外结果,请使用以下技术之一:

  • 按字母顺序指定ENUM列表。
  • 通过编码ORDER BY CAST(col AS AS)或ORDER BY CONCAT(col)确保列按字面顺序排序,而不是索引编号。



枚举限制



枚举值不能是一个表达式,即使是一个评估为字符串值的表达式。


例如,此CREATE TABLE语句不起作用,因为CONCAT函数不能用于构造枚举值:

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


您也不能使用用户变量作为枚举值。 这一对语句不起作用:



SET @mysize = 'medium';

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


我们强烈建议您不要使用数字作为枚举值,因为它不会将数据保存在合适的TINYINT或SMALLINT类型上,并且很容易混淆字符串和底层数值(可能不一样) 如果您错误地引用了ENUM值。 如果确实使用数字作为枚举值,则始终将其用引号括起来。 如果省略引号,则该数字被视为索引。 请参阅处理枚举文字以查看引用的数字是否可能被错误地用作数字索引值。



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


11.4.5 SET 类型



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


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


''

'one'

'two'

'one,two'



SET列最多可以有64个不同的成员。 一个表在其ENUM和SET列中可以有不超过255个唯一元素列表定义,被视为一个组。


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


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


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


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


mysql> SELECT set_col+0 FROM tbl_name;


如果一个数字存储在SET列中,那么在数字的二进制表示中设置的位将确定列值中的集合成员。 对于指定为SET('a','b','c','d')的列,成员具有以下十进制和二进制值。





如果为此列指定9的值,即二进制数为1001,则选择第一个和第四个SET值成员'a'和'd',结果值为'a,d'。





对于包含多个SET元素的值,插入值时列出元素的顺序无关紧要。 数值中列出给定元素的次数也无关紧要。 稍后检索该值时,该值中的每个元素都显示一次,并根据元素在创建表时指定的顺序列出元素。 例如,假设列被指定为SET('a','b','c','d'):



mysql> CREATE TABLE myset (col SET('a', 'b', 'c', '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';


第一个语句中查找包含第一个成员的值。 第二个查找完全匹配。 小心第二种类型的比较。 将设置值与'val1,val2'进行比较会与'val2,val1'比较值返回不同的结果。 您应该按照它们在列定义中列出的顺序指定值。



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

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3125656/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-09-09

  • 博文量
    2646
  • 访问量
    42244