MySQL数据类型 - 字符串数据类型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL数据类型 - 字符串数据类型相关的知识,希望对你有一定的参考价值。

1.ENUM类型

ENUM是一个字符串对象,其值从允许值列表中选择,创建表时,这些允许的值在列定义中明确列出。

ENUM类型具有以下优点:

●在列具有有限可能值的情况下压缩数据存储。指定为输入值的字符串将自动编码为数字。

●查询和输出可读性强。在查询结果中这些数字被转换回相应的字符串。

需要考虑的潜在问题:

创建和使用ENUM列

枚举值必须是带引号的字符串文本。例如,可以创建一个具有ENUM列的表:
技术图片

将100万行值为‘medium‘的记录插入此表将需要100万字节的存储空间,而如果将实际字符串‘medium‘存储在VARCHAR列中,则需要600万字节的存储空间。

枚举文本的索引值

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

●列定义中的枚举元素被分配了索引号,从1开始。

●空字符串(‘‘)错误值的索引值为0。这意味着您可以使用以下SELECT语句查找分配了无效ENUM值的行:

技术图片

●NULL值的索引为NULL。

●这里的术语"index"是指枚举值列表中的一个位置。它与表索引无关。

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

索引
NULL NULL
‘‘ 0
‘Mercury‘ 1
‘Venus‘ 2
‘Earth‘ 3

ENUM列最多可以有65535个不同元素。

如果在数值上下文中检索ENUM值,则返回列值的索引。例如,可以从ENUM列中检索数值,如下所示:

技术图片

类似SUM()或AVG()这样的函数需要数值参数,在必要时会将参数转换为数字。对于ENUM值,将在计算中使用索引号。

枚举字面量的处理

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

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

如果将数字存储到ENUM列中,则该数字将被视为可能的索引值,并且存储的值是具有该索引的枚举成员。(但是,这对于LOAD DATA语句不起作用,因为此语句将所有输入都视为字符串。)如果数值被引号引起来,则如果枚举值列表中没有匹配的字符串,则仍将其解释为索引。由于这些原因,不建议使用看起来像数字的ENUM值定义枚举列,因为这很容易使人混淆。例如,以下列具有枚举成员"0"、"1"和"2",但数字索引值为1、2和3:
技术图片

如果存储2,它将被解释为一个索引值,并变为"1"(索引值是2)。如果存储‘2‘,则它与枚举值匹配,因此存储为‘2‘。如果存储‘3‘,则它与任何枚举值都不匹配,因此它被视为索引并变为‘2‘(索引值是3)。

技术图片
要确定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子句时出现意外结果,可以使用以下技术之一:

●按字母顺序指定枚举列表。

●通过ORDER BY CAST(col AS CHAR) 或者 ORDER BY CONCAT(col)语句确保列是按词汇顺序排序的,而不是按索引号排序。

枚举限制

枚举值不能是表达式,甚至不能是计算结果为字符串值的表达式。

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

技术图片

也不能将用户变量用作枚举值。下面的语句不起作用:

技术图片

强烈建议您不要使用数字作为枚举值,因为它不能保存在适当的TINYINT或SMALLINT类型中,而且如果不正确地引用枚举值,很容易混淆字符串和隐含的数字值(可能不同)。如果使用数字作为枚举值,请始终将其括在引号中。如果省略引号,则该数字视为索引。

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

2.SET类型

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

例如,列指定为SET(‘one‘, ‘two‘) NOT NULL可以具有以下任何值:
技术图片

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

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

创建表时,将自动从表定义中的集合成员值中删除尾随空格。

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

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

mysql以数字方式存储SET值,存储值的最低位对应于第一个集合成员。如果在数字上下文中检索一个集合值,则检索到的值具有与构成列值的集合成员相对应的位集。例如,可以从如下所示的集合列中检索数值:

技术图片

如果一个数字存储在SET列中,则在该数字的二进制表示形式中设置的位决定了列值中的集合成员。对于指定为SET(‘a‘,‘b‘,‘c‘,‘d‘)的列,成员具有以下十进制和二进制值。

SET 成员 十进制值 二进制值
‘a‘ 1 0001
‘b‘ 2 0010
‘c‘ 4 0100
‘d‘ 8 1000

如果将值9赋给此列,即二进制的1001,则选择第一个和第四个SET值成员‘a‘和‘d‘,结果值为‘a,d‘。

对于包含多个集合元素的值,插入该值时元素的列出顺序并不重要。给定元素在值中列出的次数也无关紧要。稍后检索该值时,该值中的每个元素都会出现一次,其中的元素将根据在表创建时指定它们的顺序列出。假设列被指定为SET(‘a‘,‘b‘,‘c‘,‘d‘):
技术图片

如果分别插入值‘a,d‘,‘d,a‘,‘a,d,d‘,‘a,d,a‘和‘d,a,d‘:

技术图片

当检索时所有值都显示为‘a,d‘:
技术图片

如果将SET列设置为不支持的值,则忽略该值并发出警告:

技术图片

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

SET值按数字排序。NULL值的排序在非NULL集合值之前。

类似SUM()或AVG()等需要数值参数的函数,在必要时将参数转换为数字。对于SET值,将转换成数值使用。

通常,使用FIND_IN_SET()函数或LIKE运算符搜索SET值:

技术图片

第一条语句查找set_col包含集合成员‘value‘的行。第二个类似,但不完全一样:它查找set_col在任何部分包含‘value‘的行,甚至是另一个集合成员的子字符串。

还允许以下语句:
技术图片

这些语句中的第一个语句查找包含第一个集合成员的值。第二个要查找一个精确匹配值。要当心第二种类型的比较。将集合值与‘val1,val2‘进行比较所返回的结果与将值与‘val2,val1‘进行比较所返回的结果不同。应该按照列定义中列出的顺序指定值。

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

英文版地址:
https://dev.mysql.com/doc/refman/8.0/en/enum.html

以上是关于MySQL数据类型 - 字符串数据类型的主要内容,如果未能解决你的问题,请参考以下文章

MySql 数据类型

MySQL 数据类型:数值日期和时间字符串等类型详解

MySQL数据类型 - 字符串数据类型

MYSQL 的数据类型

跟王老师学MySQL:MySQL数据类型之字符类型

MySQL- 数据类型