6.2 列类型
MySQL 支持大量的列类型,它们可以被分为 3 类:数字类型、日期和时间类型以及字符串(字符)类型。这个章节首先给出可用类型的概述,并且总结各类型所需的存储需求,然后提供各类型中的类型范畴更详细的描述。概述有意地简化了。更详细的说明应该参考特写列类型的附加信息,例如你能为其指定值的允许格式。
MySQL 支持的列类型在下面列出。下列代码字母用于描述中:
M 指出最大的显示尺寸。最大的显示尺寸长度为 255。 D 适用于浮点类型。指出跟随在十进制小数点后的数字数量。最大可能值为 30,但不应大于 M-2。
方括号 (“[” and “]”) 指定可选的类型修饰部份。
注意,如果为一个列指定了 ZEROFILL,MySQL 将自动为这个列添加 UNSIGNED 属性。
警告:你应该知道当在两个整数类型值中使用减法时,如有一个为 UNSIGNED类型,那么结果也是无符号的。查看章节 6.3.5 Cast 函数。
TINYINT[(M)] [UNSIGNED] [ZEROFILL] 一个非常小的整数。有符号的范围是 -128 到 127。无符号的范围是 0 到 255。 BIT BOOL 它们是 TINYINT(1) 的同义词。 SMALLINT[(M)] [UNSIGNED] [ZEROFILL] 一个小整数。有符号的范围是 -32768 到 32767。无符号的范围是 0 到 65535。 MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL] 一个中等大小的整数。有符号的范围是 -8388608 到 8388607。无符号的范围是 0 到 16777215。 INT[(M)] [UNSIGNED] [ZEROFILL] 一个正常大小的整数。有符号的范围是 -2147483648 到 2147483647。无符号的范围是 0 到 4294967295。 INTEGER[(M)] [UNSIGNED] [ZEROFILL] INT 的同义词。 BIGINT[(M)] [UNSIGNED] [ZEROFILL] 一个大的整数。有符号的范围是 -9223372036854775808 到 9223372036854775807。无符号的范围是 0 到 18446744073709551615。 你应该知道的有关 BIGINT 列的一些事情: 所有的算术运算均是用有符号的 BIGINT 或 DOUBLE 值来完成的,因此你不应该使用大于 9223372036854775807 (63 bits) 的无符号大整数,除了位函数之外!如果你这样做了,结果中的某些大数字可能会出错,因为将 BIGINT 转换成 DOUBLE 时产生了舍入错误。MySQL 4.0 在下列情况下可以处理 BIGINT: 在一个 BIGINT 列中使用整数存储一个大的无符号值。 在 MIN(big_int_column) 和 MAX(big_int_column)中。 当两个操作数都是整数时使用操作符 (+、-、*、等)。 通常你可以在一个 BIGINT 列中以字符串方式存储的一个精确的整数。在这种情况下,MySQL 将执行一个字符串到数字的转换,包括无 intermediate 的双精度表示法。 当两个参数均是整数值时,“-”、“+”和 “*” 将使用 BIGINT 运算!这就意味着,如果两个大整数的乘积(或函数的结果返回整数)的结果大于 9223372036854775807 时,你可能会得到意想不到的结果。 FLOAT(precision) [UNSIGNED] [ZEROFILL] 一个浮点型数字。precision 可以是 <=24 作为一个单精度的浮点数字和介于 25 和 53 之间作为一个双精度的浮点数字。这些类型与下面描述的 FLOAT 和 DOUBLE 类型相似。 FLOAT(X) 有与相应的 FLOAT 和 DOUBLE 类型同样的范围,但是显示尺寸和十进制小数位数是未定义的。 在 MySQL 3.23 中,它是一个真实的浮点值。而在 MySQL 早期的版本中,FLOAT(precision) 通常有 2 小数位。 注意,由于在 MySQL 中所有的计算都是以双精度执行的,所以使用 FLOAT 可能带来一些意想不到的问题。 查看章节 A.5.6 解决没有匹配行的问题。 该句法是为了 ODBC 兼容而提供的。 FLOAT[(M,D)] [UNSIGNED] [ZEROFILL] 一个小的(单精度) 浮点数字。允许的值是 -3.402823466E+38 到 -1.175494351E-38、0 和 1.175494351E-38 到 3.402823466E+38。如果 UNSIGNED 被指定,负值是不允许的。M 是显示宽度,D 是小数位数。FLOAT 没有参数或有 X <= 24 的 FLOAT(X) 代表一个单精度的浮点数字。 DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL] 一个正常大小的(双精度)浮上数字。允许的值是 -1.7976931348623157E+308 到 -2.2250738585072014E-308、0 和 2.2250738585072014E-308 到 1.7976931348623157E+308。如果 UNSIGNED 被指定,负值是不允许的。M 是显示宽度,D 是小数位数。DOUBLE 没胡参数或有 25 <= X <= 53 的 FLOAT(X) 代表一个双精度的浮点数字。 DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL] REAL[(M,D)] [UNSIGNED] [ZEROFILL] 它们是 DOUBLE 同义词。 DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL] 一个未压缩(unpacked)的浮点数。运作如同一个 CHAR 列:“unpacked” 意味着数字是以一个字符串存储的,值的每一位将使用一个字符。小数点并且对于负数,“-” 符号不在 M 中计算(但是它们的空间是被保留的)。如果 D 是 0,值将没有小数点或小数部份。DECIMAL 值的最大范围与 DOUBLE 一致,但是对于一个给定的 DECIMAL 列,实际的范围可以被所选择的 M 和 D 限制。如果 UNSIGNED 被指定,负值是不允许的。 如果 D 被忽略,缺省为 0。如果 M 被忽略,缺省为 10。 在 MySQL 3.23 以前,M 参数必须包含符号与小数点所需的空间。 DEC[(M[,D])] [UNSIGNED] [ZEROFILL] NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL] DECIMAL 的同义词。 DATE 一个日期。支持的范围是 '1000-01-01' 到 '9999-12-31'。MySQL 以 'YYYY-MM-DD' 格式显示 DATE 值,但是允许你以字符串或数字给一个 DATE 列赋值。查看章节 6.2.2.2 DATETIME、DATE 和 TIMESTAMP 类型。 DATETIME 一个日期和时间的组合。支持的范围是 '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59'。MySQL 以'YYYY-MM-DD HH:MM:SS' 格式显示 DATETIME 值,但是允许你以字符串或数字给一个 DATETIME 列赋值。查看章节 6.2.2.2 DATETIME、DATE 和 TIMESTAMP 类型。 TIMESTAMP[(M)] 一个时间戳。范围是 '1970-01-01 00:00:00' 到 2037 年间的任意时刻。 MySQL 4.0 和更早版本中,TIMESTAMP 值是以 YYYYMMDDHHMMSS、YYMMDDHHMMSS、YYYYMMDD 或 YYMMDD 格式显示的,它取决于 M 是否是 14 (或省略)、12、8 或 6,但是允许你以字符串或数字给一个 TIMESTAMP 列赋值。 从 MySQL 4.1 开始,TIMESTAMP 以 'YYYY-MM-DD HH:MM:DD' 格式作为字符返回。如果你你希望以数字形式返回则必须在该时间戳字段后加上 +0。不同的时间戳长度是不支持的。从 MySQL 4.0.12 开始,选项 --new 可以被用来使服务器与 4.1 一样运作。 TIMESTAMP 列有益于记录一个 INSERT 或 UPDATE 操作的日期和时间,因为如果你自己没有给它赋值,它将被自动地设置为最近一次操作的日期和时间。也可以通过给它赋一个 NULL 而使它设置为当前的日期和时间。查看章节 6.2.2 Date 和 Time 类型。 参数 M 只影响一个 TIMESTAMP 列的显示格式;它的值总是占用 4 个字节存储。 注意,当 TIMESTAMP(M) 列的 M 是 8 或 14 时,它返回的是数字而其它的 TIMESTAMP(M) 列返回的是字符串。这仅仅是为了可以可靠地转储并恢复到其它格式的表中。 查看章节 6.2.2.2 DATETIME、DATE 和 TIMESTAMP 类型。 TIME 一个时间。范围是 '-838:59:59' 到 '838:59:59'。MySQL 以 'HH:MM:SS' 格式显示 TIME 值,但是允许你使用字符串或数字来给 TIME 列赋值。查看章节 6.2.2.3 TIME 类型。 YEAR[(2|4)] 一个 2 或 4 位数字格式的年(缺省为 4 位)。允许的值是 1901 到 2155、0000(4 位年格式) 以及使用 2 位格式的 1970-2069 (70-69)。MySQL 以 YYYY 格式显示 YEAR 值,但是允许你使用字符串或数字来给 YEAR 列赋值。(YEAR 类型在 MySQL 3.22 之前不支持。) 查看章节 6.2.2.4 YEAR 类型。 [NATIONAL] CHAR(M) [BINARY] 一个定长的字符串,当存储时,总是以空格填满右边到指定的长度。M 的范围是 0 到 255 (在 MySQL 3.23 版本之前为 1 到 255)。当该值被检索时,尾部空格将被删除。CHAR 值根据缺省的字符集进行忽略大小写的排索与比较,除非指定了关键词 BINARY。 NATIONAL CHAR (或短形式 NCHAR) 是以 ANSI SQL 方式定义一个 CHAR 列,它将使用缺省的字符集。这在 MySQL 中是默认的。 CHAR 是 CHARACTER 的缩写。 MySQL 允许以 CHAR(0) 类型建立一个列。一些老程序运行时必需一个列,却又并不使用这个列的值,你就不得不为了适应它而建立该列,在这情况下,CHAR(0) 将是很有益的。当需要一个列仅保存两个值时:一个为 CHAR(0)(该列没有定义为 NOT NULL),这将仅占用一个比特位来存储 2 个值:NULL 或 ""。查看章节 6.2.3.1 CHAR 和 VARCHAR 类型。 CHAR 这是 CHAR(1) 的同义词。 [NATIONAL] VARCHAR(M) [BINARY] 一个变长的字符串。注意:尾部的空格在存储时将会被删除(这与 ANSI SQL 约规不同)。M 的范围是 0 到 255 (在 MySQL 4.0.2 之前的版本中是 1 到 255)。 VARCHAR 值以大小写忽略方式进行排索与比较,除非关键词 BINARY 被指定。查看章节 6.5.3.1 隐式的列定义变化。 VARCHAR 是 CHARACTER VARYING 的缩写。 查看章节 6.2.3.1 CHAR 和 VARCHAR 类型。 TINYBLOB TINYTEXT 一个 BLOB 或 TEXT 列,最大长度为 255 (2^8 - 1) 个字符。查看章节 6.5.3.1 隐式的列定义变化。查看章节 6.2.3.2 BLOB 和 TEXT 类型。 BLOB TEXT 一个 BLOB 或 TEXT 列,最大长度为 65535 (2^16 - 1) 个字符。查看章节 6.5.3.1 隐式的列定义变化。查看章节 6.2.3.2 BLOB 和 TEXT 类型。 MEDIUMBLOB MEDIUMTEXT 一个 BLOB 或 TEXT 列,最大长度为 16777215 (2^24 - 1) 个字符。查看章节 6.5.3.1 隐式的列定义变化。查看章节 6.2.3.2 BLOB 和 TEXT 类型。 LONGBLOB LONGTEXT 一个 BLOB 或 TEXT 列,最大长度为 4294967295 (2^32 - 1) 个字符。查看章节 6.5.3.1 隐式的列定义变化。注意,由于服务器/客户端的协议以及 MyISAM 表通常有一个 16M 每通信包/表行的限制,你仍然不能使用这个类型的整个范围。查看章节 6.2.3.2 BLOB 和 TEXT 类型。 ENUM('value1','value2',...) 一个枚举类型。一个仅能有一个值的字符串对象,这个值选自值列 'value1'、'value2'、...、NULL 或特殊的 "" 出错值。一个 ENUM 列可以有最大 65535 不同的值。查看章节 6.2.3.3 ENUM 类型。 SET('value1','value2',...) 一个集合。一个能有零个或更多个值的字符串对象,其中每个值必须选自值列'value1'、'value2'、...。一个 SET 列可以有最大 64 个成员。查看章节 6.2.3.4 SET 类型。 6.2.1 数字类型MySQL 支持所有的 ANSI/ISO SQL92 数字类型。这些类型包括准确数字的数据类型(NUMERIC、DECIMAL、INTEGER 和 SMALLINT),也包括近似数字的数据类型(FLOAT、REAL和 DOUBLE PRECISION)。关键词 INT 是 INTEGER 的同义词,关键词 DEC 是 DECIMAL 的同义词。
NUMERIC 和 DECIMAL 类型被 MySQL 以同样的类型实现,这在 SQL92 标准中是允许的。他们用于保存对准确精度有重要要求的值,例如与金钱有关的数据。当以它们中的之一声明一个列时,精度和数值范围可以(通常是)被指定;例如:
salary DECIMAL(5,2)
在这个例子中,5 (精度(precision)) 代表重要的十进制数字的数目,2 (数据范围(scale)) 代表在小数点后的数字位数。在这种情况下,因此,salary 列可以存储的值范围是从 -99.99 到 99.99。(实际上 MySQL 在这个列中可以存储的数值可以一直到 999.99,因为它没有存储正数的符号)。
译者注:
M 与D 对DECIMAL(M, D) 取值范围的影响 类型说明 取值范围(MySQL < 3.23) 取值范围(MySQL >= 3.23) DECIMAL(4, 1) -9.9 到 99.9 -999.9 到 9999.9 DECIMAL(5, 1) -99.9 到 999.9 -9999.9 到 99999.9 DECIMAL(6, 1) -999.9 到 9999.9 -99999.9 到 999999.9 DECIMAL(6, 2) -99.99 到 999.99 -9999.99 到 99999.99 DECIMAL(6, 3) -9.999 到 99.999 -999.999 到 9999.999 # 在MySQL 3.23 及以后的版本中,DECIMAL(M, D) 的取值范围等于早期版本中的DECIMAL(M + 2, D) 的取值范围。 注释结束:
在 ANSI/ISO SQL92 中,句法 DECIMAL(p) 等价于 DECIMAL(p,0)。同样的,在执行被允许决定值 p 的地方,句法 DECIMAL 等价于 DECIMAL(p,0)。MySQL 目前还不支持 DECIMAL/NUMERIC 数据类型的这些变体形式中的任一种。一般来说这并不是一个严重的问题,通过明确地控制精度和数值范围可以得到这些类型的主要功能益处。
DECIMAL 和 NUMERIC 值是作为字符串存储的,而不是作为二进制浮点数,以便保护这些值的十进制精确度。一个字符用于数值的每一位、小数点(如果 scale > 0) 和 “-” 符号(对于负值)。如果 scale 是 0,DECIMAL 和 NUMERIC 值不包含小数点或小数部分。
DECIMAL 和 NUMERIC 值的最大范围与 DOUBLE 一致,但是对于一个给定的 DECIMAL 或 NUMERIC 列,它的实际范围可制定该列时的 precision 或 scale 限制。当这样的列被赋给了小数点的位数超过 scale 所指定的值时,该将根据 scale 进行四舍五入。当一个 DECIMAL 或 NUMERIC 列被赋与一个大小超过指定(或缺省)的 precision and scale 的限止范围时,MySQL 以该列范围的端点值存储该值。
示例(译者注):mysql> CREATE TABLE `tA` ( -> `id` int(4) unsigned zerofill NOT NULL, -> `salary` decimal(5,2), -> PRIMARY KEY (`id`) -> ) TYPE=MyISAM; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO `tA` (`id`, `salary`) -> VALUES (1, -99.99), # 以数字方式插入 -> (2, "99.99"), # 以字符串方式插入 -> (3, -999.99), -> (4, "9999.99"), -> (5, -1000.00), # decimal(5,2)最小范围为 -999.99 该值插入时结果为 -999.99 -> (6, "10000.00"), # decimal(5,2)最大范围为 9999.99 该值插入时结果为 9999.99 -> (7, "-99.999"), # 小数位数超过 scale 指定值,但因以字符串方式插入,结果值仅截去多余部分 -> (8, "99.9999"), -> (9, -99.999), # 小数位数超过 scale 指定值,对该值进行四舍五入,结果为 -100.00 -> (10,99.9999); Query OK, 10 rows affected (0.00 sec) Records: 10 Duplicates: 0 Warnings: 4 mysql> SELECT * FROM `tA`; +------+---------+ | id | salary | +------+---------+ | 0001 | -99.99 | | 0002 | 99.99 | | 0003 | -999.99 | | 0004 | 9999.99 | | 0005 | -999.99 | | 0006 | 9999.99 | | 0007 | -99.99 | | 0008 | 99.99 | | 0009 | -100.00 | | 0010 | 100.00 | +------+---------+ 10 rows in set (0.00 sec) * 以上结果在 MySQL 4.0.12 中测试 示例结束(译者注)
作为对 ANSI/ISO SQL92 标准的一个扩展,MySQL 也支持上面的表格所列出的整型类型 TINYINT、MEDIUMINT 和 BIGINT。另外一个扩展是 MySQL 支持随意指定一个整型数值的显示格式,这通过在类型的基本关键词后跟一个括号来实现(例如 INT(4))。这个可选的宽度规格说明是用于在数值显示时,对某些值的宽度短于该列宽度的值进行左填补显示的,而不是为了限制在该列中存储值的宽度,也不是为了限制那些超过该列指定宽度的值的可被显示的数字位数。当与可选的扩展属性 ZEROFILL 一起使用时,缺省填补用的空格被零代替。举例来说,一个列被定义为 INT(5) ZEROFILL,插入的值 4 被检索出来时为 00004。注意,如果在一个整型列中存储一个超过显示宽度的更大值时,当 MySQL 为某些复杂的联结(join)生成临时表时,你可能会遇到问题,因为在这种情况下,MySQL 信任地认为所有的值均适合原始的列宽度。
示例(译者注):mysql> CREATE TABLE `tA` ( -> `id` int(4) unsigned zerofill NOT NULL, -> PRIMARY KEY (`id`) -> ) TYPE=MyISAM; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO `tA` (`id`) -> VALUES (1),(12),(1234),(12345678); Query OK, 4 rows affected (0.01 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM `tA`; +----------+ | id | +----------+ | 0001 | | 0012 | | 1234 | | 12345678 | +----------+ 4 rows in set (0.00 sec) * 以上结果在 MySQL 4.0.12 中测试 示例结束(译者注)
所有的整型类型可以有一个可选(非标准的)属性 UNSIGNED。如果希望在一个列中只允许正值并且需要一个稍大一点的数字范围,就可以使用无符号值。
从 MySQL 4.0.2 开始,浮点类型也可以存在 UNSIGNED。 与整型类型一致的,这个属性可以防止在该列中存在负值。而与整型类型不一致的,该列的高部范围仍然与原范围保持一致。
FLOAT 类型被用于表示近似数字的数值类型。ANSI/ISO SQL92 标准允许一个可选的精度说明(但不是指数的范围),跟在 关键词 FLOAT 后的括号内。MySQL 实现也支持这个可选的精度规格说明。当关键词被用于一个列的类型说明而没有精度规格说明时,MySQL 使用四个字节来存储该字段值。在关键词 FLOAT 后的括号里给出两个数字,这种变形的句法也是被支持的。使用这个选项时,第一个数字继续表示值存储所占的字节数,第二个数字指定能被存储和显示的跟随在小数点后的位数(就像 DECIMAL 和 NUMERIC)。当 MySQL 被要求为这样的一个列存储一个小数点后的小数位数超过指定值的数值时,该值将会被四舍五入,去除额外的位。
示例(译者注):mysql> CREATE TABLE `tA` ( -> `id` int(4) unsigned zerofill NOT NULL, -> `float_date` float(4,2) unsigned NOT NULL, -> PRIMARY KEY (`id`) -> ) TYPE=MyISAM; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO `tA` (`id`,`float_date`) -> VALUES (1, -100), # 插入无效的负值 -> (2, 100.99), # 以数字方式插入 -> (3, "100.99"), # 以字符串方式插入 -> (4, "100.99999"), # 小数位数超过指定倍数,该值进行四舍五入 -> (5, 100.99999), -> (6, "100.9911"), -> (7, 100.9911); Query OK, 7 rows affected (0.00 sec) Records: 7 Duplicates: 0 Warnings: 1 mysql> SELECT * FROM `tA`; +------+------------+ | id | float_date | +------+------------+ | 0001 | 0.00 | | 0002 | 100.99 | | 0003 | 100.99 | | 0004 | 101.00 | | 0005 | 101.00 | | 0006 | 100.99 | | 0007 | 100.99 | +------+------------+ 7 rows in set (0.00 sec) * 以上结果在 MySQL 4.0.12 中测试 示例结束(译者注)
REAL 和 DOUBLE PRECISION 类型不接受精度规格说明。作为对 ANSI/ISO SQL92 标准的扩展,MySQL 接受 DOUBLE 作为 DOUBLE PRECISION 类型的一个同义词。标准要求 REAL 的精度比用于 DOUBLE PRECISION 的更小,而与之相反的,MySQL 以 8 字节的双精度浮点值(当不以“ANSI 模式”运行时)来实现两者。为了得到最大的可移植性, 近似数字的数值存储所需代码应该使用没有精度或小数位数规格说明的 FLOAT 或 DOUBLE PRECISION 类型。
当试图在一个数字列中存储一个超过该列允许范围的值时,MySQL 会剪切该值到范围内的适当端点值,并以结果值代替存储。
举例来说,一个整型列的范围是 -2147483648 到 2147483647。如果试图在一个 INT 列中插入值 -9999999999,该值将会被剪切到该范围的低部端点,以 -2147483648 代替存储。同样的,如果试图插入 9999999999,2147483647 将被代替存储。
如果 INT 列是 UNSIGNED的,列的范围大小是一致的,不过它的端点移动到了 0 和 4294967295。如果你试图存储 -9999999999 和 9999999999,而实际列中存储的值将会变成 0 和 4294967296。
对于 ALTER TABLE、LOAD DATA INFILE、UPDATE 和多行 INSERT 语句,由于剪切发生的转换,将以“Warnings”被报告。
类型 占用字节 从 到 TINYINT 1 -128 127 SMALLINT 2 -32768 32767 MEDIUMINT 3 -8388608 8388607 INT 4 -2147483648 2147483647 BIGINT 8 -9223372036854775808 9223372036854775807 6.2.2 Date 和 Time 类型
日期和时间类型有 DATETIME、DATE、TIMESTAMP、TIME 和 YEAR。每一个类型均有合法值的范围,当给它们赋于一个真正不合法的值时,这些值将会被“零”代替。注意,MySQL 允许存储某个“不严格地”合法的日期,例如 1999-11-31。这样做的原因是,我们认为应用程序有责任来处理日期合法性的检查,而不是由 SQL 服务器来处理。为了“加快”对日期的检查,MySQL 仅检查月份应在 0-12 范围内,以及天在 0-31 范围内。因为上面所述的范围定义方式,MySQL 因而允许你在一个 DATE 或 DATETIME 列中存储日或月日均为 0 的日期。当一个应用程序希望存储一个出生日期,而你并不知准确的出生日月时,这将变得非常有用。在这种情况下,你可以简单地以 1999-00-00 或 1999-01-00 形式存储日期。(当然你不能期望 DATE_SUB() 或 DATE_ADD 之类的函数能正确地处理这样的日期,并得到正确的值。)
当使用日期和时间类型工作时,这里有一些要记住的总则:
MySQL 对一个给定的日期或时间类型以标准的格式进行检索,但是它会努力以各种格式匹配解释你所提供的(例如,当你指定一个值,将其赋给一个日期或时间类型或与之比较时)。然而,只在下面部分所描述的格式是被支持的。期望你能够提供合法的值,如果你使用其它格式的值,可能会造成无法预料的结果。 尽管 MySQL 会尝试以各种格式解释值,它通常期望日期的年部分放在最左边。日期必须以年-月-日次序给出(例如, '98-09-04'),而不是其它地方常用的月-日-年或日-月-年次序(例如,'09-04-98'、'04-09-98')。 如果一个值被用于在数字的语境中,MySQL 将自动地将一个日期或时间类型值转换成数字,反之亦然。 当 MySQL 遇到一个日期或时间类型的值超出范围或对该类型是一个不合法的值时(查看这个章节的开头部分),它会将该类型的值变换到“零”值。(例外的是超出范围的 TIME 值将被剪切为适当的 TIME 范围端点值。) 下表每种类型的“零”值格式: 列类型 “零”值 DATETIME '0000-00-00 00:00:00' DATE '0000-00-00' TIMESTAMP 00000000000000 (长度取决于显示格式) TIME '00:00:00' YEAR 0000 “零”值是特殊的,但是你可以以表中显示的值来明确地存储或引用他们。你也可以使用值'0' 或 0,这更易于书写。 在 MyODBC 2.50.12 和以上的版本中,“零”值的日期和时间值通过 MyODBC 将被自动转换成 NULL,因为 ODBC 不能够处理这样的值。 6.2.2.1 Y2K 问题和日期类型
MySQL 自身是 Y2K 安全的(查看章节 1.2.5 2000 年兼容性),但是呈交给 MySQL 的值可能并不是。任何一个包含 2 位年份的值是存在二义性的,因为世纪值是未知的。这样的值必须被解释为 4 位格式,因为 MySQL 内部使用四位存储年份。
对于 DATETIME、DATE、TIMESTAMP 和 YEAR 类型,MySQL 使用下列规则解释存在二义性的年份值:
在范围 00-69 内的年值被转换为 2000-2069。 在范围Y 70-99 内的年值被转换为 1970-1999。记住,这些规则仅仅提供对于你的数据含义的合理猜测。如果 MySQL 使用的探索法无法得到正确的值,你应该以包含 4 位年份的格式提供一个明确的值。
ORDER BY 将以适当的顺序对 2 位 YEAR/DATE/DATETIME 类型排序。
注意,某些像 MIN() 和 MAX() 之类的函数会将 TIMESTAMP/DATE 转换为一个数字。这就意味着,一个 2 位年份的时间戳将完全不能与这些函数一同工作。在这种情况下,解决的办法是将 TIMESTAMP/DATE 转换为 4 位年份格式或者使用诸如 MIN(DATE_ADD(timestamp,INTERVAL 0 DAYS)) 的方法。
6.2.2.2 DATETIME、DATE 和 TIMESTAMP 类型
DATETIME、DATE 和 TIMESTAMP 类型是相似的。这个章节描述了它们的特性以及它们的相似点与不同点。
DATETIME 类型可用于需要同时包含日期和时间信息的值。MySQL 以 'YYYY-MM-DD HH:MM:SS' 格式检索与显示 DATETIME 类型。支持的范围是 '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59'。(“支持”的含义是,尽管更早的值可能工作,但不能保证他们均可以。)
DATE 类型可用于需要一个日期值而不需要时间部分时。MySQL 以 'YYYY-MM-DD' 格式检索与显示 DATE 值。支持的范围是 '1000-01-01' 到 '9999-12-31'。
TIMESTAMP 列类型提供了一种类型,通过它你可以以当前操作的日期和时间自动地标记 INSERT 或UPDATE 操作。如果一张表中有多个 TIMESTAMP 列,只有第一个被自动更新。
自动更新第一个 TIMESTAMP 列在下列任何条件下发生:
列值没有明确地在一个 INSERT 或 LOAD DATA INFILE 语句中被指定。 列值没有明确地在一个 UPDATE 语句中被指定,并且其它的一些列值已发生改变。(注意,当一个 UPDATE 设置一个列值为它原有值时,这将不会引起 TIMESTAMP 列的更新,因为,如果你设置一个列值为它当前值时,MySQL 为了效率为忽略更新。) 明确地以 NULL 设置 TIMESTAMP 列。第一个列以外其它 TIMESTAMP 列,可以设置到当前的日期和时间,只要将该列赋值 NULL 或 NOW()。
任何 TIMESTAMP 列均可以被设置一个不同于当前操作日期与时间的值,这通过为该列明确指定一个你所期望的值来实现。这也适用于第一个 TIMESTAMP 列。这个选择性是很有用的,举例来说,当你希望 TIMESTAMP 列保存该记录行被新添加时的当前的日期和时间,但该值不再发生改变,无论以后是否对该记录行进行过更新:
当该记录行被建立时,让 MySQL 设置该列值。这将初始化该列为当前日期和时间。 以后当你对该记录行的其它列执行更新时,为 TIMESTAMP 列值明确地指定为它原来的值。另一方面,你可能发现更容易的方法,使用 DATETIME 列,当新建记录行时以 NOW() 初始化该列,以后在对该记录行进行更新时不再处理它。
示例(译者注):
mysql> CREATE TABLE `tA` ( -> `id` int(3) unsigned NOT NULL auto_increment, -> `date1` timestamp(14) NOT NULL, -> `date2` timestamp(14) NOT NULL, -> PRIMARY KEY (`id`) -> ) TYPE=MyISAM; Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO `tA` SET `id` = 1; Query OK, 1 row affected (0.02 sec) # 没有明确地指定第一个 timestamp 列值,该列值被设为插入的当前时刻 # 没有明确地指定其它的 timestamp 列值,MySQL 则认为插入的是一个非法值,而该列值被设为0 mysql> INSERT INTO `tA` VALUES (2, NOW(), NULL); Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM `tA`; +----+----------------+----------------+ | id | date1 | date2 | +----+----------------+----------------+ | 1 | 20030503104118 | 00000000000000 | | 2 | 20030503104254 | 20030503104254 | +----+----------------+----------------+ 2 rows in set (0.00 sec) mysql> UPDATE `tA` SET `id` = 3 WHERE `id` = 1; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 # 对某一记录行进行了更新,第一个 timestamp 列值也将被更新 mysql> UPDATE `tA` SET `id` = 2 WHERE `id` = 2; Query OK, 0 rows affected (0.00 sec) Rows matched: 1 Changed: 0 Warnings: 0 # MySQL 忽略了这次操作,第一个 timestamp 列值不会被更新 mysql> SELECT * FROM `tA`; +----+----------------+----------------+ | id | date1 | date2 | +----+----------------+----------------+ | 3 | 20030503104538 | 00000000000000 | | 2 | 20030503104254 | 20030503104254 | +----+----------------+----------------+ 2 rows in set (0.00 sec) mysql> UPDATE `tA` SET `id` = 1,`date1`=`date1` WHERE `id` = 3; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 # 明确地指定了第一个 timestamp 列值为它原有值,该值将不会被更新 mysql> SELECT * FROM `tA`; +----+----------------+----------------+ | id | date1 | date2 | +----+----------------+----------------+ | 1 | 20030503104538 | 00000000000000 | | 2 | 20030503104254 | 20030503104254 | +----+----------------+----------------+ 2 rows in set (0.00 sec) * 以上结果在 MySQL 4.0.12 中测试 示例结束(译者注)
TIMESTAMP 值可以从 1970 到 2037 之间的任一时刻,精度为一秒。其值作为数字显示。
MySQL 检索与显示 TIMESTAMP 值的格式取决于它的显示尺寸,描述如下表。“完整”的 TIMESTAMP 格式是 14 位的,但是 TIMESTAMP 列可以以一个更短的显示尺寸建立:
列类型 显示格式 TIMESTAMP(14) YYYYMMDDHHMMSS TIMESTAMP(12) YYMMDDHHMMSS TIMESTAMP(10) YYMMDDHHMM TIMESTAMP(8) YYYYMMDD TIMESTAMP(6) YYMMDD TIMESTAMP(4) YYMM TIMESTAMP(2) YY所有的 TIMESTAMP 列均有一个相同的存储尺寸,而不考虑显示尺寸的大小。最常见的显示尺寸为 6、8、12 和 14。你可以在表创建时指定一个任意的显示尺寸,但是值 0 或 比 14 大的值将会被强制定义为列长 14。在从 1 ~ 13 范围内的奇数会被强制为下一个更大的偶数。
例如(译者注): 字段定义 强制字段长度 TIMESTAMP(0) TIMESTAMP(14) TIMESTAMP(15) TIMESTAMP(14) TIMESTAMP(1) TIMESTAMP(2) TIMESTAMP(5) TIMESTAMP(6)
注意:从 MySQL 4.1 开始,TIMESTAMP 以 'YYYY-MM-DD HH:MM:DD' 格式作为字符串返回。不同的时间戳长度不再被支持。
译者注:如果你你希望在 MySQL 4.1 中以数字形式返回时间戳,则必须在该时间戳字段后加上 +0。从 MySQL 4.0.12 开始,选项 --new 可以被用来使服务器与 4.1 一样运作。
你可以使用常用的格式集中的任何一个指定 DATETIME、DATE 和 TIMESTAMP 值:
一个 'YYYY-MM-DD HH:MM:SS' 或 'YY-MM-DD HH:MM:SS' 格式的字符串。一个“宽松”的语法是被允许的:以任何标点符号作为日期部分和时间部分中的定界符。例如,'98-12-31 11:30:45'、'98.12.31 1+30+45'、'98/12/31 11*30*45' 和 '98@12@31 11^30^45' 均是等价的。 一个 'YYYY-MM-DD' 或 'YY-MM-DD' 格式的字符串。这里,一个“宽松”的语法同样也是被允许的:例如,'98.12.31'、'98-12-31'、'98/12/31' 和 '98@12@31' 是等价的。 一个无定界符的 'YYYYMMDDHHMMSS' 或 'YYMMDDHHMMSS' 格式的字符串,只要字符串看起来像是一个日期。例如,'19970523091528' 和 '970523091528' 均被解释为 '1997-05-23 09:15:28',但是 '971122129015' 却是违法的(它的分部分是无意义的),该值被插入时将变成 '0000-00-00 00:00:00'。 一个无定界符的 'YYYYMMDD' 或 'YYMMDD' 格式的字符串,只要字符串看起来像是一个日期。例如,'19970523' 和 '970523' 被解释成为 '1997-05-23',但是 '971332' 却是违法的(它的月和日部分是无意义的),该值被插入时将变成 '0000-00-00'。 一个 YYYYMMDDHHMMSS 或 YYMMDDHHMMSS 格式的数字,只要数字看起来像是一个日期。例如,19830905132800 和 830905132800 被解释成为 '1983-09-05 13:28:00'。 一个 YYYYMMDD 或 YYMMDD 格式的数字,只要数字看起来像是一个日期。例如,19830905 和 830905 被解释成为 '1983-09-05'。 在一个 DATETIME、DATE 或 TIMESTAMP 语境中,一个函数的返回值将随之而变化,例如 NOW() 或 CURRENT_DATE。非法的 DATETIME、DATE 或 TIMESTAMP 值将会被转换到适当形式的“零”值('0000-00-00 00:00:00'、'0000-00-00' 或 00000000000000)。
对于以字符串格式指定的包含日期定界符的值,不必要为小于 10 的月或天的值指定 2 位数字。'1979-6-9' 等同于 '1979-06-09'。同样的,对于以字符串指定的包含时间定界符的值,不必要为小于 10 的时、分或秒指定 2 位数字。'1979-10-30 1:2:3' 等同于 '1979-10-30 01:02:03'。
以数字指定的值应该是 6、8、12 或 14 位长。如果数字是 8 或 14 位长的,该值将被假定为年份是由头 4 位数字给出的 YYYYMMDD 或 YYYYMMDDHHMMSS 格式。如果数字是 6 或 12 数字长,它将被假定为年份是由头 2 位数字给出的 YYMMDD 或 YYMMDDHHMMSS 格式。不是这些长度之一的数字通过在值前补零到最接近的长度后解释。
以没有定界符的字符串格式指定的值通过它们给出的长度来解释。如果字符串是 8 或 14 个字符长,则假定年份由前 4 个字符给出。否则,年份由前 2 个字符给出。对于字符串中出现的多个部分,字符串以从左到右的顺序被解释,以找出年、月、日、时、分和秒值。这就意味着,你不就使用少于 6 个字符的字符串。例如,如果指定 '9903' ,你可能认为它代表 1999年3月,但你将会发现MySQL 会将一个“零”值插入到你的表中。这是因为,年份和月份分别为 99 和 03,但是日期部分丢失(为 0),因此这个值是不合法的。
TIMESTAMP 列总是以完全精度存储给定的合法值,而不考虑显示尺寸的大小。这包含几个含义:
赋值时总是给出年、月和日,即使你的列类型定义为 TIMESTAMP(4) 或 TIMESTAMP(2)。否则,该值将是不合法的,而被 0 代替存储。示例(译者注):
mysql> CREATE TABLE `tA` ( -> `id` int(3) unsigned NOT NULL auto_increment, -> `date1` timestamp(4) NOT NULL, -> PRIMARY KEY (`id`) -> ) TYPE=MyISAM; Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO `tA` (`id`,`date1`) -> VALUES (1,NULL), # 插入当前日期和时间 -> (2,0305), # 以数字格式给出值,而值长度小于 6 ,在最左边补 0 至 6 位数字 -> (3,'0305');# 以字符串格式给出值,而值长不包括年、月和日,因而是一个非法值 Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 1 mysql> SELECT * FROM `tA`; +----+-------+ | id | date1 | +----+-------+ | 1 | 0305 | | 2 | 0003 | | 3 | 0000 | +----+-------+ 3 rows in set (0.00 sec) * 以上结果在 MySQL 4.0.12 中测试 示例结束(译者注)
如果以 ALTER TABLE 拓展一个 TIMESTAMP 窄列,以前被“隐蔽”的信息将被显示出来。示例(译者注):
* 接上例结果 mysql> ALTER TABLE `ta` CHANGE `date1` `date1` TIMESTAMP(11); Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 # 设置 `date1` 为 TIMESTAMP(11),MySQL 会自动将其转化为 TIMESTAMP(11) mysql> SELECT * FROM `tA`; +----+--------------+ | id | date1 | +----+--------------+ | 1 | 030503150142 | | 2 | 000305000000 | | 3 | 000000000000 | +----+--------------+ 3 rows in set (0.00 sec) * 以上结果在 MySQL 4.0.12 中测试 示例结束(译者注):
同样的,缩小一个 TIMESTAMP 列的宽度不会引起信息的丢失,除了在感觉上值在被显示时显示了较少的信息。 尽管 TIMESTAMP 列值是以全部精度存储的,但是 UNIX_TIMESTAMP() 是唯一能直接操作内部存储值的函数。其它的函数操作的是格式化后的检索的值。这就意味着不能够使用诸如 HOUR() 或 SECOND() 之类的函数,除非相关部分存在于格式化后的 TIMESTAMP 值中。例如,在小于 10 的显示格式上,为了使 TIMESTAMP 列中的 HH 部分能够显示,显示格式的尺寸必须不小于 10,因此在一个更短的 TIMESTAMP 列值上使用 HOUR() 将会产生一个无意义的结果。示例(译者注):
* 接上例结果 # 下列示例结果与上述结果相悖 mysql> ALTER TABLE `ta` CHANGE `date1` `date1` TIMESTAMP(4); Query OK, 3 rows affected (0.02 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM `tA`; +----+-------+ | id | date1 | +----+-------+ | 1 | 0305 | | 2 | 0003 | | 3 | 0000 | +----+-------+ 3 rows in set (0.01 sec) mysql> SELECT HOUR(`date1`) FROM `tA`; +---------------+ | Hour(`date1`) | +---------------+ | 15 | | 0 | | NULL | +---------------+ 3 rows in set (0.02 sec) mysql> SELECT SECOND(`date1`) FROM `tA`; +-----------------+ | second(`date1`) | +-----------------+ | 42 | | 0 | | NULL | +-----------------+ 3 rows in set (0.01 sec) * 以上结果在 MySQL 4.0.12 中测试 示例结束(译者注):
在某种程序上,你可以将一个日期值赋给另一种日期类型的对象。然而,这可能会使值产生改变或丢失一部分信息。
如果将一个 DATE 值赋给一个 DATETIME 或 TIMESTAMP 对象,结果值的时间部分将被设为 '00:00:00',因为 DATE 值不包含时间信息。 如果将一个 DATETIME 或 TIMESTAMP 值赋给一个 DATE 对象,结果值的时间部分被删除,因为 DATE 类型不能存储时间信息。 记住,尽管 DATETIME、DATE 和 TIMESTAMP 值全都可以用同样的格式集来指定,但所有类型不都有同有同样的值范围。例如,TIMESTAMP 值不能早于 1970 或晚于 2037。这就意味着,一个日期例如 '1968-01-01',作为一个 DATETIME 或 DATE 值是合法的,但不是一个有效的 TIMESTAMP 值,当它被赋于一个这样的对象时,它将被转换为 0。当指定日期值时,当心某些失误:
你可能会被以字符串指定值时所允许的宽松格式欺骗。例如,一个值如 '10:11:12' 的,因为分界符 “:” 可能看起来像是一个时间值, 但是当它被用于一个日期语境中时,它将被解释成为 '2010-11-12' 年。而值 '10:45:15' 将被转换成 '0000-00-00',因为 '45' 是一个不合法的月份。 MySQL 服务器仅对日期的有效性执行基本的检验:天为 00-31,月为 00-12,年为 1000-9999。任何不是这个范围内的日期将被转换为 0000-00-00。请注意,这仍然允许你存储一个无效的日期例如2002-04-31。它允许一个 WEB 应用程序不进行进一步的检查而存储一个表单中的数据。为了确保一个日期值的有效性,在你的应用程序里执行有效性检查。 以两位数字指定年份是存在二义性的,因为世纪是未知的。MySQL 以下面的规则解释一个 2 位年份值: 00-69 范围的年份值被转换为 2000-2069。 70-99 范围的年份值被转换为 1970-1999。 6.2.2.3 TIME 类型
MySQL 以 'HH:MM:SS' 格式(或对大的小时值时使用 'HHH:MM:SS' 格式)检索和显示 TIME 值。TIME 值的范围可以从 '-838:59:59' 到 '838:59:59'。小时部分可以这么大的原因 是,TIME 类型不仅可以用于表示一天的时间(这一定不会超过 24 小时),而且可以用来表示所经过的时间或两个事件之间的时间间隔(这可能比 24 小时大许多或是一个负值)。
TIME 值可以多种格式指定:
一个 'D HH:MM:SS.fraction' 格式的字符串。(注意,MySQL 仍然不能为时间列存储毫秒“fraction”)下面所示的任一种“宽松”的语法均可以被使用:HH:MM:SS.fraction、HH:MM:SS、HH:MM、D HH:MM:SS、D HH:MM、D HH 或 SS。这里的 D 是一个在 0-33 之间的日期。 一个无定界符的 'HHMMSS' 格式的字符串,只要字符串看起来像是一个时间。例如:'101112' 可被理解为 '10:11:12',但是 '109712' 是不合法的(它有一个无意义的分钟部分),当被插入时会转换为 '00:00:00'。 一个 HHMMSS 格式的数字,只要数字看起来像一个时间。例如,101112 可被理解为 '10:11:12'。下面的任一格式均可被正常理解:SS、MMSS、HHMMSS、HHMMSS.fraction。注意,MySQL 仍不能保存 毫秒(fraction)部分。 在一个 TIME 语境中,函数(例如 CURRENT_TIME)的返回值将会返一个合理的格式。对于以字符串指定的包含时间定界符的 TIME 值,不必要为小于 10 的时、分或秒指定 2 位数字。'8:3:2' 与 '08:03:02' 是一致的。
将“短”的 TIME 值赋给另一个 TIME 列时要格外小心。如果没有冒号,MySQL 使用最右位代表秒的假设来解释值。(MySQL 将 TIME 值解释为经过的时间,而不是时刻)。例如,你可能会认为 '1112' and 1112 的意思就是 '11:12:00' (11 点过 12 分),但是 MySQL 却将它解释为 '00:11:12' (11 分,12 秒)。同样的,'12' 和 12 被解释为 '00:00:12'。有冒号的 TIME 值,由于冒号的存在,通常认为是处理过的时刻。这就是说,'11:12' 就意味着是 '11:12:00',而不是 '00:11:12'。
如果值超出了 TIME 的范围,但是其它分、秒部分是合法的,它将被剪切到取值范围的适当端点。例如,'-850:00:00' 和 '850:00:00' 将被分别转换为 '-838:59:59' 和 '838:59:59'。
不合法的 TIME 值将被转换为 '00:00:00'。注意,因为 '00:00:00' 自身是一个合法的 TIME 值,这就没有办法区分,存储在一个表中的 '00:00:00',原来的值是否就是指定为 '00:00:00' 或是一个不合法的值。
6.2.2.4 YEAR 类型
YEAR 类型是一个以 1 个字节描述年份的类型。
MySQL 以 YYYY 格式检索和显示一个 YEAR 值。范围是 1901 到 2155。
可以以多个格式指定 YEAR 值:
一个在 '1901' 到 '2155' 范围之内的 4 位字符串。 一个在 1901 到 2155 范围之内的 4 位数字。 一个在 '00' 到 '99' 范围之内的 2 位字符串。'00' 到 '69' 和 '70' 到 '99' 范围内的值将被分别转换到 2000 到 2069 和 1970 到 1999 范围内的 YEAR 值。 一个在 1 到 99 范围之内的数字。1 到 69 和 70 到 99 范围内的值将被分别转换到 2001 到 2069 和 1970 到 1999 范围内的 YEAR 值。注意,两位数字的范围与两位字符串的范围稍稍有点不同,因为你不能直接地以数字指定一个零值,将它解释为 2000。你必须 以一个 '0' 或 '00' 格式的字符串指定它,否则它将被解释为 0000。 在一个 YEAR 的语境中,函数(例如 NOW())的返回值将会返回一个合理的格式。不合法的 YEAR 值将被转换为 0000。
6.2.3 字符串类型
字符串类型有 CHAR、VARCHAR、BLOB、TEXT、ENUM 和 SET。这个章节描述这些类型是如何工作的,它们的存储需求,以及在你的查询中如何使用它们。
类型 最大尺寸 字节 TINYTEXT 或 TINYBLOB 2^8-1 255 TEXT 或 BLOB 2^16-1 (64K-1) 65535 MEDIUMTEXT 或 MEDIUMBLOB 2^24-1 (16M-1) 16777215 LONGBLOB 2^32-1 (4G-1) 4294967295 6.2.3.1 CHAR 和 VARCHAR 类型CHAR 和 VARCHAR 类型是很相似的,但是它们被存储与检索的方式有些不同。
一个 CHAR 列的长度被固定为你创建表进所声明的长度。长度可以是 1 和 255 之间的任一值。(从 MySQL 3.23 之后,CHAR 的长度可以是 0 到 255。)当 CHAR 值被存储时,他们被用空格在右边填补到指定长度。当 CHAR 值被检索时,尾部的空格被截除。
VARCHAR 列的值是变长的字符串。你可以声明一个 VARCHAR 列在 1 到 255, 就像对 CHAR 列一样。然而,与 CHAR 相反的,VARCHAR 值只以所需的字符数存储,另加一个字节存储记录的长度。值并不被填补;相反的,当被存储时,尾部的空格被截除。(这个截除空格方式不同于 ANSI SQL 规约。)
如果将一个超过列最大长度的值赋给一个 CHAR 或 VARCHAR 列,该值将截断以适合它。
下表通过在 CHAR(4) 和 VARCHAR(4) 列中存储不同的字符串的结果显示了两种类型列的不同:
值 CHAR(4) 存储需求 VARCHAR(4) 存储需求 '' ' ' 4 字节 '' 1 字节 'ab' 'ab ' 4 字节 'ab' 3 字节 'abcd' 'abcd' 4 字节 'abcd' 5 字节 'abcdefgh' 'abcd' 4 字节 'abcd' 5 字节在各种情况下,CHAR(4) 和 VARCHAR(4) 列的检索值均是一样的,因为在 CHAR 列上检索值的尾部空格会被截除。
CHAR 和 VARCHAR 列值以省略字母大小写的方式进行排序和比较,除非在表建立时 BINARY 属性被指定。BINARY 属性意味着,该列值根据 MySQL 服务器正在运行的机器的 ASCII 表顺序进行字母大小写敏感的方式排序和比较。BINARY 并不影响该列如何被存储和检索。
BINARY 属性是有粘性的。这就意味着,如果一个被标记为 BINARY 的列被用于一个表达式中,整个表达式将作为一个 BINARY 值被比较。
在表创建时,MySQL 可能会隐式地改变一个 CHAR 或 VARCHAR 列的类型。查看章节 6.5.3.1 隐式的列定义变化。
6.2.3.2 BLOB 和 TEXT 类型
一个 BLOB 是一个可以保存一可变数量的数据的二进制大对象。四个 BLOB 类型(TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB)之间的不同仅仅在于他们能保存值的最大长度不一致。查看章节 6.2.6 列类型存储需求。
四个 TEXT 类型(TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT)对应与四个 BLOB 类型,并且有相同的最大长度和存储需求。在 BLOB 和 TEXT 类型之间的唯一差别就是,对 BLOB 值是以字母大小写敏感的方式进行排序和比较的,而对 TEXT 值以忽略字母大小写方式进行排序和比较。换句话说,TEXT 是一个忽略字母大小写的 BLOB。
如果将一个超过列类型最大长度的值赋给一个 BLOB 或 TEXT 列,该值将被截断以适应它。
在大多数方面,可以将一个 TEXT 列看作是一个你所希望大 VARCHAR 列。同样的,BLOB 列可以看作是一个 VARCHAR BINARY 列。差别就在于:
在 MySQL 3.23.2 和更新的版本中,可以在 BLOB 和 TEXT 列上建立索引。而较老版本的 MySQL 是不支持的。 当 BLOB and TEXT 列值被存储时,尾部的空格不会被剪切,这与 VARCHAR 列是不一样的。 BLOB 和 TEXT 列不可以有 DEFAULT 值。MyODBC 以 LONGVARBINARY 定义 BLOB 值,以 LONGVARCHAR 定义 TEXT 值。
因为 BLOB 和 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,该列的缺省值将是该列表所允许值的第一个成员。每个枚举值均有一个索引值:
在列说明中列表值所允许的成员值被从 1 开始编号。 空字符串错误值的索引值为 0。这就意味着,你可以使用下面所示的 SELECT 语句找出被赋于无效 ENUM 值的记录行。mysql> SELECT * FROM tbl_name WHERE enum_col=0; NULL 值的索引值为 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 个字节。
本文地址:http://com.8s8s.com/it/it21256.htm