和 TEXT 值可以非常地长,在使用它们时可能会遇到某些限制:
-
如果希望在一个
BLOB 或 TEXT 列上使用 GROUP BY 和 ORDER BY ,必须将该列值转换为一个定长对象。这样做的标准做法是使用 SUBSTRING 函数。例如:
mysql> SELECT comment FROM tbl_name,SUBSTRING(comment,20) AS substr
-> ORDER BY substr;
如果你不这样做,只有列值的前 max_sort_length 个字节用于排序。max_sort_length 缺省的值为 1024;在启动 mysqld 服务时,可以使用 -O 选项对它进行更改。可以在一个包含 BLOB 或 TEXT 值的表达式上进行分组,通过指定列的位置或使用一个别名:
mysql> SELECT id,SUBSTRING(blob_col,1,100) FROM tbl_name GROUP BY 2;
mysql> SELECT id,SUBSTRING(blob_col,1,100) AS b FROM tbl_name GROUP BY b;
-
一个
BLOB 或 TEXT 对象的最大尺寸由其类型决定,但是在客户端和服务器之间实际所能传送的最大值,是由可用内存总数和通讯缓冲区的大小来决定的。你可以改变报文缓冲区的大小,但必须在服务器端与客户端同时这么做。查看章节 5.5.2 调节服务器参数。
注意,每个 BLOB 或 TEXT 值在内部由一个独立分配的对象表示。这与其它所有的列类型不一样,当表被打开时,它们被按每列分配一次存储。
6.2.3.3 ENUM 类型
ENUM 是一个字符串对象,其值通常选自一个允许值列表中,该列表在表创建时的列规格说明中被明确地列举。
在下列某些情况下,值也可以是空串("" ) 或 NULL :
-
如果将一个无效值插入一个
ENUM (即,一个不在允许值列表中的字符串),空字符串将作为一个特殊的错误值被插入。事实上,这个字符串有别于一个“普通的”空字符串,因为这个字符串有个数字索引值为 0。稍后有更详细描述。
-
如果一个
ENUM 被声明为 NULL ,NULL 也是该列的一个合法值,并且该列的缺省值也将为 NULL 。如果一个 ENUM 被声明为 NOT NULL ,该列的缺省值将是该列表所允许值的第一个成员。
每个枚举值均有一个索引值:
例如,指定为 ENUM("one", "two", "three") 的一个列,可以有下面所显示的任一值。每个值的索引值也如下所示:
值 索引值
NULL NULL
"" 0
"one" 1
"two" 2
"three" 3
换个枚举最大可以有 65535 个成员值。
从 MySQL 3.23.51 开始,当表被创建时,ENUM 值尾部的空格将会自动删除。
当为一个 ENUM 列赋值时,字母的大小写是无关紧要的。然而,以后从列中检索出来的值的大小写却是匹配于创建表时所指定的允许值。
如果在一个数字语境中检索一个ENUM ,列值的索引值将被返回。例如,你可以像这样使用数字值检索一个 ENUM 列:
mysql> SELECT enum_col+0 FROM tbl_name;
如果将一个数字存储到一个 ENUM 中,数字被当作为一个索引值,并且存储的值是该索引值所对应的枚举成员。(但是,这在 LOAD DATA 将不能工作,因为它视所有的输入均为字符串。)
在一个 ENUM 字符串中存储数字是不明智的,因为它可能会打乱思维。
ENUM 值依照列规格说明中的列表顺序进行排序。(换句话说,ENUM 值依照它们的索引号排序。)举例来说,对于 ENUM("a", "b") "a" 排在 "b" 后,但是对于 ENUM("b", "a") ,"b" 却排在 "a" 之前。空字符串排在非空字符串前,NULL 值排在其它所有的枚举值前。为了防止意想不到的结果,建议依照字母的顺序定义 ENUM 列表。也可以通过使用 GROUP BY CONCAT(col) 来确定该以字母顺序排序而不是以索引值。
如果希望得到一个 ENUM 列的所有可能值,可以使用 SHOW COLUMNS FROM table_name LIKE enum_column_name 并分析第二列的 ENUM 定义。
6.2.3.4 SET 类型
SET 是一个字符串对象,它可以有 0 或更多个值,每个值均必须选自一个允许值列表中,该列表在表创建时被指定。包含多个集合成员的 SET 列值,由逗号(“,”)将各成员分隔。由此推论,SET 成员值自身不应该包含逗号。
例如,一个指定为 SET("one", "two") NOT NULL 的列可以有下列任一值:
""
"one"
"two"
"one,two"
一个 SET 最大可以有 64 个不同的成员。
从 3.23.51 开始,当表被创建时,SET 值尾部的空格将被自动地删除。
MySQL 以数字值存储 SET 值,以被存储值的低阶比特位(bit)对应于第一个集合成员。如果在一个数字语境中检索一个 SET 值,检索的值把比特位设置为对应组成列值的集合成员。例如,你可以使用下面所示的示例从一个 SET 列中检索出一个数字:
mysql> SELECT set_col+0 FROM tbl_name;
如果将一个数字存储到一个 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 成员的值,当你插入值时,无所谓以什么顺序列出成员。也无所谓给出的值被列举了多少次。当以后检索该值时,在值中的每个成员将出现一次,根据他们在表创建时所指定的顺序列出成员。例如,如果一个列被定义为 SET("a","b","c","d") ,那么,"a,d" 、"d,a" 和 "d,a,a,d,d" 在被检索时均将被视为 "a,d" 。
如果将一个不支持的值赋于一个 SET 列,该值将被忽略。
SET 以数字顺序排序。NULL 值排在非 NULL SET 值之前。
通常,可以使用 LIKE 操作符或 FIND_IN_SET() 函数执行在一个 SET 列上的 SELECT :
mysql> SELECT * FROM tbl_name WHERE set_col LIKE ''''%value%'''';
mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET(''''value'''',set_col)>0;
但是,下列示例也可以工作:
mysql> SELECT * FROM tbl_name WHERE set_col = ''''val1,val2'''';
mysql> SELECT * FROM tbl_name WHERE set_col & 1;
第一个语句寻找一个精确的匹配。第二个语句寻找包含第一个集合成员的值。
如果希望得到一个 SET 列的所有可能值,可以使用 SHOW COLUMNS FROM table_name LIKE set_column_name 并分析第二列的 SET 定义。
6.2.4 为列选择正确的类型
为了更有效地使用存储空间,在任何情况下均尝试使用最精确的类型。例如,如果一个整数列被用于在 1 和 99999 之间的值,MEDIUMINT UNSIGNED 是最好的类型。
精确地表示货币值是一个常见的问题。在 MySQL 中,可以使用 DECIMAL 类型。它是作为一个字符串存储的,因而不会发生精度损失的情况。如果精度不是太重要的,那 DOUBLE 类型也是一个不错的选择。
对于高精度,总是能转换一个存储在 BIGINT 中的定点类型。这将允许你以整型进行任何的计算,并在必要的时候将结果转换回浮点值。
6.2.5 使用来自其它的数据库引擎的列类型
为了更容易地使用为其它供应商的 SQL 实现而编写的代码,MySQL 以下表所示的形式映射列类型。这些映射使得从其它数据库引擎移动表到 MySQL 更容易:
其它提供商的类型 MySQL 类型
BINARY(NUM) CHAR(NUM) BINARY
CHAR VARYING(NUM) VARCHAR(NUM)
FLOAT4 FLOAT
FLOAT8 DOUBLE
INT1 TINYINT
INT2 SMALLINT
INT3 MEDIUMINT
INT4 INT
INT8 BIGINT
LONG VARBINARY MEDIUMBLOB
LONG VARCHAR MEDIUMTEXT
MIDDLEINT MEDIUMINT
VARBINARY(NUM) VARCHAR(NUM) BINARY
列类型映射在表创建时发生。如果你使用其它供应商使用的类型创建一个表,然后发出一个 DESCRIBE tbl_name 语句,MySQL 将使用相等价的 MySQL 类型报告表结构。
6.2.6 列类型存储需求
每个由 MySQL 支持的列类型的存储需求按类型在下面列出。
6.2.6.1 数字类型存储需求
列类型 存储需求
TINYINT 1 字节
SMALLINT 2 字节
MEDIUMINT 3 字节
INT 4 字节
INTEGER 4 字节
BIGINT 8 字节
FLOAT(X) 4 if X <= 24 or 8 ,if 25 <= X <= 53
FLOAT 4 字节
DOUBLE 8 字节
DOUBLE PRECISION 8 字节
REAL 8 字节
DECIMAL(M,D) M+2 字节 if D > 0,M+1 字节 if D = 0 (D +2, if M < D )
NUMERIC(M,D) M+2 字节 if D > 0, M+1 字节 if D = 0 (D +2, if M < D )
6.2.6.2 日期和时间类型存储需求
列类型 存储需求
DATE 3 字节
DATETIME 8 字节
TIMESTAMP 4 字节
TIME 3 字节
YEAR 1 字节
6.2.6.3 字符串类型存储需求
列类型 存储需求
CHAR(M) M 字节, 1 <= M <= 255
VARCHAR(M) L +1 字节, where L <= M and
1 <= M <= 255
TINYBLOB , TINYTEXT L +1 字节,
where L < 2^8
BLOB , TEXT L +2 字节,
where L < 2^16
MEDIUMBLOB , MEDIUMTEXT L +3 字节,
where L < 2^24
LONGBLOB , LONGTEXT L +4 字节,
where L < 2^32
ENUM(''''value1'''',''''value2'''',...) 1 or 2 字节, 取决于枚举值的数量(最大值为 65535)
SET(''''value1'''',''''value2'''',...) 1, 2, 3, 4 or 8 字节, 取决于集合成员数量(最大 64 个成员)
VARCHAR 和 BLOB 和 TEXT 类型是变长的类型,其存储需求取决于列值的实际长度(上表中以 L 表示),而不是取决于类型的最大可能尺寸。例如,一个 VARCHAR(10) 列可以保存最大长度为 10 个字符的字符串。实际存储需求为字符串长度 (L ),再加上 1 个字节用于记录该字符串的长度。对于字符串 ''''abcd'''' ,L 为 4,它的存储需求为 5 字节。
BLOB 和 TEXT 类型需要 1、2、3 或 4 字节记录列值的长度,这取决于该类型的最大可能长度。查看章节 6.2.3.2 BLOB 和 TEXT 类型。
如果一个表包含任何变长类型的列类型,记录格式也将是变长的。注意,当一个表被创建时,在某种情况下,MySQL 会将一个列从一个变长类型转换成一个定长类型,或相反的。查看章节 6.5.3.1 隐式的列定义变化。
一个 ENUM 对象的大小取决于不同枚举值的数量。一个字节被用于枚举时,最大可支持 255 个可能值。2 个字节被用于枚举时,最大可支持到 65535 个值。查看章节 6.2.3.3 ENUM 类型。
一个 SET 对象的大小取决于不同集合成员的数量。如果集合的大小是 N ,则对象占用 (N+7)/8 个字节,四舍五入为 1、2、3、4 或 8 个字节。一个 SET 可以有最多 64 个成员。查看章节 6.2.3.4 SET 类型。
MyISAM 表的记录行最大尺寸为 65534 字节。每个 BLOB 和 TEXT 列只占用相对于这个尺寸中的 5-9 个字节。
|