简介
每一个常量、变量和参数都有数据类型,它用来指定一定的存储格式、约束和有效范围。MySQL提供了多种数据类型,主要包括数值型、字符串类型、日期和时间类型。不同的MySQL版本支持的数据类型可能会稍有不同,用户可以通过查询相应版本的帮助文件来获得具体信息。在MySQL的命令行窗口输入:? int命令,会看到如下输出:
mysql> ? int Name: ‘INT‘ Description: INT[(M)] [UNSIGNED] [ZEROFILL] A normal-size integer. The signed range is -2147483648 to 2147483647. The unsigned range is 0 to 4294967295. URL: http://dev.mysql.com/doc/refman/5.6/en/numeric-type-overview.html |
Description中的几个标记在官网中有详细的说明:
M:代表maximum,表示最大值;
[]:代表可选项
翻译:一个一般大小的整型,带符号范围是-2147483648到 2147483647。不带符号范围是0到4294967295。
复制最下方的URL,在浏览器中打开,可以看到官方给出的帮助文档,含有对MySQL相关内容的详细说明。
数值类型
MySQL支持所有标准SQL中的数值类型,其中包括严格数值类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值类型(FLOAT、REAL和DOUBLEPRECISION),并在此基础上做了扩展。扩展后增加了TINYINT、DEDIUMINT和BIGINT这3种长度不同的整型,并增加了BIT类型,用来存放位数据。下表中列出了MySQL5中支持的所有数值类型。
整数类型 |
字节 byte |
最小值 |
最大值 |
||
有符号 |
无符号 |
有符号 |
无符号 |
||
TINYINT |
1 |
-128(-) |
0 |
127() |
255() |
SMALLINT |
2 |
-32768(-) |
0 |
32767 |
65535 |
MEDIUMINT |
3 |
-8388608(-) |
0 |
8388607 |
1677215 |
INT、INTEGER |
4 |
-2147483648(-) |
0 |
2147483647 |
4294967295 |
BIFINT |
8 |
-9223372036854775808(-) |
0 |
() |
() |
浮点数类型 |
字节 |
最小值 |
最大值 |
||
FLOAT |
4 |
||||
DOUBLE |
8 |
||||
定点数类型 |
字节 |
描述 |
|||
DEC(M,D) DECIMAL(M,D) |
M+2 |
最大取值范围与DOUBLE相同,给定DECIMAL的有效取值范围由M和D决定 |
|||
位类型 |
字节 |
最小值 |
最大值 |
||
BIT(M) |
1~8 |
BIT(1) |
BIT(64) |
整数类型
在整数类型中,按照取值范围和存储方式不同,分为tinyint、smallint、dediumint、int和bigint这5个类型。如果超出类型范围的操作,会发生“Out of range”错误提示。为了避免此类问题发生,在选择数据类型时要根据应用的实际情况确定其取值范围,最后根据确定的结果慎重选择数据类型。
对于整型数据,MySQL还支持在类型名称后面的小括号内指定显示宽度,例如int(5)表示当数值宽度小于5位的时候在数字前面填满宽度,如果不显示指定宽度则默认为int(11)。一般配合zerofill使用,顾名思义,zerofill就是用“0”填充的意思,也就是在数字位数不够的空间用“0”填满。以下几个例子分别描述了填充前后的区别。
(1) 创建表t1,有id1和id2两个字段,指定其数值宽度分别为int和int(5):
mysql> CREATE TABLE t1(id1 int,id2 int(5)); Query OK, 0 rows affected (0.04 sec) mysql> desc t1; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id1 | int(11) | YES | | NULL | | | id2 | int(5) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ 2 rows in set (0.01 sec) |
(2) 在id1和id2中都插入数值1,可以发现格式没有异常;
mysql> INSERT INTO t1 VALUES(1,1); Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM t1; +------+------+ | id1 | id2 | +------+------+ | 1 | 1 | +------+------+ 1 row in set (0.00 sec) |
(3) 分别修改id1和id2的字段类型,加入zerofill参数:
mysql> ALTER TABLE t1 MODIFY id1 INT ZEROFILL; Query OK, 1 row affected (0.06 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> ALTER TABLE t1 MODIFY id2 INT(5) ZEROFILL; Query OK, 1 row affected (0.06 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM t1; +------------+-------+ | id1 | id2 | +------------+-------+ | 0000000001 | 00001 | +------------+-------+ 1 row in set (0.00 sec) |
可以发现,在数值前面用字符“0”填充了剩余的苦读。大家可能会有所疑问,设置了宽度限制后,如果插入大于宽度限制的值,会不会截断或者插不进去报错?不会,还是按照类型的实际精度进行保存,这时,宽度格式实际已经没有意义,左边不会再填充任何的“0”字符。下面在表t1中插入数值1,id2中插入数值1111111,位数为7,大于id2的显示位数5,再观察一下测试结果:
mysql> INSERT INTO t1 VALUES(1,1111111); Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM t1; +------------+---------+ | id1 | id2 | +------------+---------+ | 0000000001 | 00001 | | 0000000001 | 1111111 | +------------+---------+ 2 rows in set (0.00 sec) |
很显然,如上面所说,id2中显示了正确的数值,并没有受宽度限制影响。
在定义列类型时,经常会看到类型后跟着一个小括号,小括号中有个数字,如int(5)。有些地方解释说,该列最大能保存的数值长度为5位。这种解释是否正确?做下面的测试:
(1) 将t1中id1,id2的zerofill修饰去掉
mysql> ALTER TABLE t1 MODIFY id1 INT ; Query OK, 2 rows affected (0.07 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> ALTER TABLE t1 MODIFY id2 INT(5) ; Query OK, 2 rows affected (0.06 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> desc t1; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id1 | int(11) | YES | | NULL | | | id2 | int(5) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ 2 rows in set (0.01 sec) |
(2) 是否能正确插入记录(1,1111111)
mysql> INSERT INTO t1 VALUES(1,1111111); Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM t1; +------+---------+ | id1 | id2 | +------+---------+ | 1 | 1 | | 1 | 1111111 | | 1 | 1111111 | +------+---------+ 3 rows in set (0.00 sec) |
INSERT语句正确执行,可见“int(5):该列最大能保存的数值长度为5位”此种解释是错误的。在MySQL中对于整型来说,完成某列能保存数据最大长度限定的是数据类型,而不是数据类型后的小括号。进一步测试:
(3) 将t1表中id1修改为int(99)
mysql> ALTER TABLE t1 MODIFY id2 INT(99) ; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> DESC t1; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id1 | int(11) | YES | | NULL | | | id2 | int(99) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ 2 rows in set (0.01 sec) |
int类型所能表示的最大值为无符号时4294967295(),10位,但是id2修改为int(99)竟然执行无误,为何?再次否定了“int(5):该列最大能保存的数值长度为5位”的谬论。
既然无用,要之何用?有用,但不是上面所说的“限定最大长度”。对于int(5)的解释,有准确的说法是:
INT(M) M指示最大显示宽度。最大有效显示宽度是5个字符。显示宽度与存储大小或类型包含的值的范围无关。而且,该参数配合zerofill使用才会在查看时有效。
官网上对M以及浮点数中的D的说明:
· M indicates the maximum display width for integer types. For floating-pointand fixed-point types, M is the total number of digits that can be stored (the precision). For string types, M isthe maximum length. The maximum permissible value of M depends on the data type.
译文: · M表示整数类型的最大显示宽度。对于浮点类型和定点类型,M表示可以存储的数字的总数(精度)。对于字符串类型,M是最大长度。M的最大允许值取决于数据类型。 · D适用于浮点类型和定点类型,并表示小数点后的数字(标度)。最大值是30,但不应大于M-2。 |
大家知道int所能表示的最大值为无符号时的4294967295 (),10位,为什么默认是int(11)呢?不要忘记符号位,也就是说int最大位数是11位(字符),此处的位不可理解为二进制的位数,是十进制显示的(字符串的)长度。下面显示一个11位的int:
mysql> ALTER TABLE t1 MODIFY id2 INT(5) ; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> INSERT INTO t1 VALUES(-2147483648,1); Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM t1; +-------------+---------+ | id1 | id2 | +-------------+---------+ | 1 | 1 | | 1 | 1111111 | | 1 | 1111111 | | -2147483648 | 1 | +-------------+---------+ 4 rows in set (0.00 sec) |
可以看到最后一条记录的id1中的值是11位(字符串长度)的(包含符号位)。
所有的整数类型都有一个可选属性UNSIGNED(无符号),如果需要在字段里面保存非负数或者需要较大的上限值时,可以用此选项,它的取值范围是正常值的下限取0,上限取原值的2倍。
另外,整数类型还有一个属性:AUTO_INCREMENT。在需要产生唯一标识符或顺序值时,可利用此属性,这个属性只用于整数类型。AUTO_INCREMENT值一般从1开始,没行增加1.在插入NULL到一个AUTO_INCREMENT列时,MySQL插入一个比该列中当前最大值大1的值。一个表中最多只能有一个AUTO_INCREMENT列。对于任何想要使用AUTO_INCREMENT的列应该定义为NOT NULL,并定义为PRIMARY KEY或定义为UNIQUE键。否则会出现错误提示:
mysql> CREATE TABLE t2(id1 INT AUTO_INCREMENT,id2 INT AUTO_INCREMENT); ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key |
FLOAT、DOUBLE和DECIMAL类型
对于小数的表示,MySQL分为两种方式:浮点数和定点数。浮点数包括float(单精度)和double(双精度),而定点数只有decimal一种表示。定点数在MySQL内部以字符串形式存放,比浮点数更精确,适合用来表示货币等精度高的数据。
浮点数和定点数都可以用类型名称后加”(M,D)”的方式来进行表示,”(M,D)”表示该值一共显示M位数字(整数位+小数位,不包括小数点),其中D位位于小数点后面,M和D又称为精度和标度。例如,定义为float(7,4)的一个列可以显示为-999.9999.MySQL保存值时进行四舍五入,因此如果在float(7,4)列内插入999.00009,近似结果是999.0001。值得注意的是,浮点数后面跟”(M,D)”的用法是非标准用法,如果要用于数据库的迁移,则最好不要这么使用。float和double在不指定精度时,默认的整数位为10,默认的小数位为0.
下面通过一个例子来比较float、double和decimal三者之间的不同。
(1) 创建测试表t2,分别将id1,id2,id3字段设置为float(5,2),double(5,2),decimal(5,2):
mysql> CREATE TABLE t2 (id1 float(5,2) DEFAULT NULL,id2 double(5,2) DEFAULT NULL, id3 DECIMAL(5,2) DEFAULT NULL); |
(2) 往id1,id2,id3这三个字段中插入数据1.23:
mysql> INSERT INTO t2 VALUES(1.23,1.23,1.23); Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM t2; +------+------+------+ | id1 | id2 | id3 | +------+------+------+ | 1.23 | 1.23 | 1.23 | +------+------+------+ 1 row in set (0.00 sec) |
可以发现,数据都正确地插入了表t2.
(3) 再向id1和id2字段中插入1.234,id3中仍插入1.23:
mysql> INSERT INTO t2 VALUES(1.234,1.234,1.23); Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM t2; +------+------+------+ | id1 | id2 | id3 | +------+------+------+ | 1.23 | 1.23 | 1.23 | | 1.23 | 1.23 | 1.23 | +------+------+------+ 2 rows in set (0.00 sec) |
可以发现,虽然插入了值,但是di1和id2由于精度的限制,舍去了最后一位,数据变成了1.23。
(4) 同时向id1,id2,id3中插入1.234:
mysql> INSERT INTO t2 VALUES(1.234,1.234,1.234); Query OK, 1 row affected, mysql> SELECT * FROM t2; +------+------+------+ | id1 | id2 | id3 | +------+------+------+ | 1.23 | 1.23 | 1.23 | | 1.23 | 1.23 | 1.23 | | 1.23 | 1.23 | 1.23 | +------+------+------+ 3 rows in set (0.00 sec) |
此时发现,虽然数据都插进去,但是系统出现了Warning。id3被截断。
浮点数如果不写精度和标度,则会按照实际精度值显示,如果有精度和标度,则会自动将四舍五入后的结果插入,系统不会报错;定点数如果不写精度和标度,则按照默认值decimal(10,0)来进行操作,并且如果数据查过了精度和标度值,系统则会报错。
对于浮点数和定点数来说与整型不同,小括号中的数值将会决定该列能够保存的最值。如float(5,2),如果整数位超过(5-2)位,那么数据不能成功插入,系统会报错。但是对于小数位的长度是没有限制的,因为系统会进行截取适合的小数位进行保存,如果小数位超限,对decimal来说仅仅会提示警告,对float和double来说直接截取,连Warning也不会有。
如,向上面的表中插入(999.001,999.001,999.001),该记录是能成功插入的;但是插入(999.999,999.999,999.999)时就会报错,原因是在四舍五入后,999.999变成1000.00,整数位超过设定的(5-2)位:
mysql> INSERT INTO t2 VALUES(999.001,999.001,999.001); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> INSERT INTO t2 VALUES(999.999,999.999,999.999); ERROR 1264 (22003): Out of range value for column ‘id1‘ at row 1 |
BIT类型
对于BIT(位)类型,用于存放位字段值,BIT(M)可以用来存放多位二进制数,M范围从1~64,如果不写则默认为1位。对于位字段,直接使用SELECT明亮将不会看到结果,可以用bin()(显示为二进制格式)或者hex()(显示为十六进制格式)函数进行读取。
数据插入bit类型字段时,首先转换为二进制,如果位数允许,将成功插入,如果数据转换后的位数大于实际定义的位数,则插入失败。如定义为bit(1),向该列插入数值2时将会失败。原因是2的二进制为“10”,位数为2,大于实际定义的1位,插入失败。
日期时间类型
MySQL中有多种数据类型可以用于日期和时间的表示,不同的版本可能有所差异,下表中列出了官网上MySQL5.6中所支持的日期和时间类型。结合MySQL命令行执行 ?[DATE|TIME|DATETIME|TIMESTAMP|YEAR]命令,整理出详细的日期时间数据类型的说明:
日期和时间类型 |
字节 |
最小值 |
最大值 |
DATE |
4 |
1000-01-01 |
9999-12-31 |
DATETIME |
8 |
1000-01-01 00:00:00.000000 |
9999-12-31 23:59:59.999999 |
TIMESTAMP |
4 |
1970-01-01 00:00:01.000000(UTC) |
2038-01-19 03:14:07.999999(UTC) |
TIME |
2 |
-838:59:59.000000 |
838:59:59.000000 |
YEAR |
1 |
1901 |
2155 |
这些数据类型的主要区别如下:
. 如果要用来表示年月日,通常用DATE来表示。
. 如果要用来表示年月日时分秒,通常用DATETIME表示。
. 如果只用来表示十分面,通常用TIME来表示。
. 如果需要经常插入或更新日期为当前系统时间,则通常使用TIMESTAMP来表示。TIMESTAMP值返回后显示为“YYYY-MM-DD HH:MM:SS”格式的字符串,显示宽度固定为19个字符。如果想要获得数字值,应在TIMESTAMP列添加“+0”。
. 如果只是表示年份,可以用YEAR来表示,它比DATE占用更少的空间。YEAR有2位或是4位格式。默认是4位格式。在4位格式中,允许的值是1901~2155和0000.在两位格式中,允许的值是‘0‘to ‘69‘ 和‘70‘ to ‘99‘表示2000 ~ 2069 和1970 ~ 1999.但是,官网上给出明确说明:
TheYEAR(2) data type has certain issues that you should consider before choosingto use it. Also, as of MySQL 5.6.6, YEAR(2) is deprecated. YEAR(2) columns inexisting tables are treated as before, but YEAR(2) in new or altered tables areconverted
to YEAR(4).
意思就是2位格式的YEAR类型已经被废弃了。
每种日期类型都有一个有效值范围,如果超出这个范围,系统会进行错误提示,并将以零值来进行存储。不同日期类型零值的表示如下所示:
Data Type |
“Zero” Value |
DATE |
‘0000-00-00‘ |
TIME |
‘00:00:00‘ |
DATETIME |
‘0000-00-00 00:00:00‘ |
TIMESTAMP |
‘0000-00-00 00:00:00‘ |
YEAR |
0000 |
DATE,TIME,DATETIME
DATE,TIME,DATETIME是最常用使用的3种日期类型,以下例子在3种类型字段插入了相同的日期,来看看它们的显示结果:
mysql> CREATE TABLE t(d date,t time,dt datetime); Query OK, 0 rows affected (0.02 sec) mysql> desc t; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | d | date | YES | | NULL | | | t | time | YES | | NULL | | | dt | datetime | YES | | NULL | | +-------+----------+------+-----+---------+-------+ 3 rows in set (0.02 sec) mysql> INSERT INTO t VALUES(NOW(),NOW(),NOW()); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> SELECT * FROM t; +------------+----------+---------------------+ | d | t | dt | +------------+----------+---------------------+ | 2016-10-26 | 11:24:42 | 2016-10-26 11:24:42 | +------------+----------+---------------------+ 1 row in set (0.00 sec) |
显而易见,DATETIME是DATE和TIME的组合,用户可以根据不同的需要,来选择不同的日期或时间类型以满足不同的应用。
TIMESTAMP
创建测试表ts,字段id1为TIMESTAMP类型:
mysql> CREATE TABLE ts(id1 TIMESTAMP); Query OK, 0 rows affected (0.03 sec) mysql> desc ts; +-------+-----------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------+------+-----+-------------------+-----------------------------+ | id1 | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | +-------+-----------+------+-----+-------------------+-----------------------------+ 1 row in set (0.01 sec) |
可以发现,系统给id1自动创建了默认值CURRENT_TIMESTAMP(系统时间)。插入一个NULL值试试:
mysql> INSERT INTO ts VALUES(NULL); Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM ts; +---------------------+ | id1 | +---------------------+ | 2016-10-26 11:41:37 | +---------------------+ 1 row in set (0.00 sec) |
果然,id1中正确插入了系统日期。注意,MySQL只给表中的第一个TIMESTAMP字段设置默认值为系统日期,如果有第二个TIMESTAMP类型,则默认值设置为0值。可以手动修改默认值为其他常量日期,但是不能为CURRENT_TIMESTAMP,因为MySQL规定TIMESTAMP类型字段只能有一列的默认值为CURRENT_TIMESTAMP,如果强制修改,系统会报错。TIMESTAMP类型还有一个重要特点,就是和时区相关。当插入日期时,会先转换为本地时区后存放;而从数据库里面取出时,也同样需要将日期转换为本地时区后显示。这样,两个不同时区的用户看到的同一个日期可能是不一样的。
TIMESTAMP的取值范围为1970-01-0100:00:01.000000(UTC)到2038-01-19 03:14:07.999999(UTC),因此它不适合存放比较久远的日期。本机测试使用时区为(+8:00),所以,TIMESTAMP的下限为1970-01-01 08:00:01.000000。
TIMESTAMP和DATETIME的表示方法非常类似,区别主要有以下几点:
. TIMESTAMP支持的时间范围较小,其取值范围从19700101080001到2038年,而DATETIME是从1000-01-0100:00:00到9999-12-31 23:59:59,范围更大。
. 表中的第一个TIMESTAMP列自动设置为当前日期和时间。如果在一个TIMESTAMP列中插入NULL,则该列值将自动设置为当前的日期和时间。在插入或更新一行但不明确给TIMESTAMP列赋值时也会自动设置该列的值为当前的日期和时间,当插入的值超出取值范围时,MySQL认为该值溢出,使用“0000-00-00 00:00:00”进行填充。
. TIMESTAMP的插入和查询都受当地时区的影响,更能反映出实际的日期。而DATETIME则只能反映出插入时当地的时区,其他时区的人查看数据必然会有误差的。
字符串类型
MySQL中提供了多种对字符数据的存储类型,CHAR、VARCHAR、BINARY、VARBINART、BLOB、TEXT、ENUM、SET等。
字符串类型 |
字节 |
描述集存储需求 |
CHAR(M) |
M |
M为0~255之间的整数 |
VARCHAR(M) |
M为0~65535之间的整数,值的长度+1个字节 |
|
TINYBLOB |
允许长度0~255字节,值的长度+1个字节 |
|
BLOB |
允许长度0~65535字节,值的长度+2个字节 |
|
MEDIUMBLOB |
允许长度0~167772150字节,值的长度+3个字节 |
|
LONGBLOB |
允许长度0~4294967295字节,值的长度+4个字节 |
|
TINYTEXT |
允许长度0~255字节,值的长度+2个字节 |
|
TEXT |
允许长度0~65535字节,值的长度+2个字节 |
|
MEDIUMTEXT |
允许长度0~167772150字节,值的长度+3个字节 |
|
LONGTEXT |
允许长度0~4294967295字节,值的长度+4个字节 |
|
VARBINARY(M) |
允许长度0~M个字节的变长字节字符串,值的长度+1个字节 |
|
BINART(M) |
M |
允许长度0~M个字节的定长字节字符串 |
CHAR和VARCHAR
CHAR和VARCHAR很类似,都用来保存MySQL中较短的字符串。二者的主要区别在于存储方式的不同:CHAR列的长度固定为创建表时声明的长度,长度可以为从0~255的任何值;而VARCHAR列中的值为可变长字符串,长度可以指定为0~65535。查看MySQL的帮助:
mysql> ? VARCHAR Name: ‘VARCHAR‘ Description: [NATIONAL] VARCHAR(M) [CHARACTER SET charset_name] [COLLATE collation_name] A variable-length string. M represents the maximum column length in characters. The range of M is 0 to 65,535. The effective maximum length of a VARCHAR is subject to the maximum row size (65,535 bytes, which is shared among all columns) and the character set used. For example, utf8 characters can require up to three bytes per character, so a VARCHAR column that uses the utf8 character set can be declared to be a maximum of 21,844 characters. 译: 可变长度字符串。M表示最大长度。M的范围为0至65535。某列的实际最大长度由该列保存的值中的最大值和字符集决定。例如,一个UTF-8字符需要三个字节保存,所以VARCHAR类型使用UTF8字符集可以声明的最大长度为21844(65535÷3)。 |
以下内容译自官网:http://dev.mysql.com/doc/refman/5.6/en/char.html
(能力有限,翻译不准或不地道,请多包涵)
CHAR和VARCHAR类似,但是在存储和查询时有些不同。同时,在最大长度和是否保留结尾空格方面也有不同。 声明CHAR或VARCHAR类型时,后面的小括号内的数字指定了你想保存的最大字符长度。例如,CHAR(30)可以保存30个字符。 CHAR类型的列长度是固定的,为创建时指定的大小,取值范围是0~255。存储时,若长度小于指定的长度时,将会在末尾用空格填充到指定长度。检索时尾部的空格会被删除,但是,启用PAD_CHAR_TO_FULL_LENGTH模式时,CHAR尾部的空格将会保留。 VARCHAR列中的值是可变长字符串。长度取值范围为0~65535。某列的实际最大长度受该列保存的值中的最大值=长度和字符集影响。参考Section C.10.4, 相教于CHAR,VARCHAR值除了保存数据本身的字符串之外,还会在字符串之前附带1字节的前缀表示该字符串中的字节数。如果列声明的长度为0~255,前缀长度为1字节,超过255,则前缀长度为2字节。 非严格模式下,向CHAR或VARCHAR列中插入超过该列指定的长度值时,系统会将数据截断成指定长度的值进行保存,并且提示警告,但是在严格模式下,将会抛出异常,保存数据失败。参考Section 5.1.8, “Server 无论使用严格模式还是非严格模式,截断操作截断的都是空格时,VARCHAR类型将会保存截断后的值同时提示警告,而CHAR不会提示警告。 VARCHAR类型特性与标准SQL一致,在不填充保存时,存储和检索操作都会保留尾部的空格。 下表示例中通过向CHAR(4)和VARCHAR(4)中保存不同的字符串说明了CHAR和VARCHAR之间的区别(假定字符集为Latin1):
上表中最后一行测试数据只适用于非严格模式,在严格模式下长度超限,将会报错。 |
BINARY和VARBINARY类型
BINARY和VARBINARY类似于CHAR和VARCHAR,不同的是他们包含二进制字符串而不包含非二进制字符串。在下面的例子中,对表t中的binary字段c插入一个字符,研究一下这个字符到底是怎么样存储的。
(1)创建测试表t,字段为c BINARY(3):
mysql> CREATE TABLE t (c BINARY(3)); Query OK, 0 rows affected (0.02 sec) |
(2)往c字段中插入字符’a’:
mysql> INSERT INTO t SET c=‘a‘; Query OK, 1 row affected (0.01 sec) |
(3)分别用以下几种模式来查看c列的内容:
mysql> SELECT *,HEX(c),c=‘a‘,c=‘a\0‘,c=‘a\0\0‘ FROM t; +------+--------+-------+---------+-----------+ | c | HEX(c) | c=‘a‘ | c=‘a\0‘ | c=‘a\0\0‘ | +------+--------+-------+---------+-----------+ | a | 610000 | 0 | 0 | 1 | +------+--------+-------+---------+-----------+ 1 row in set (0.01 sec) |
可以发现,当保存BINARY值时,在值的最后通过填充”0x00”(零字节)以达到指定的字段定义长度。上例中,hex(c)值为610000,拆分为三位(定义长度为3),61/00/00转换成十进制97/0/0,对应的字符为“a00”得到保存的值为“a\0\0”。
BLOB和TEXT类型
官网原文:http://dev.mysql.com/doc/refman/5.6/en/blob.html
译文:
BLOB可以保存变长的二进制大数据。四种BLOB类型分别是:TINYBLOB、BLOB、MDEIUMBLOB和LONGBLOB。他们之间仅存储数据的最大长度不同。四种TEXT类型分别是:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。BLOB与TEXT类似,具有相同的存储上限和存储空间要求。参考Section 11.7, “Data Type Storage Requirements”. BLOB列存储为二进制(字节字符串),他们有二进制字符集和排序规则,并且基于列值中的字节的数进行比较和排序。TEXT列存储为一般的字符串,有对应的字符集,并且根据字符集进行比较和排序。 非严格模式下,向BLOB和TEXT中存入超过指定长度的值时,系统会将超出的部分进行截断并提示警告。但是在严格模式下,截断非空白的子字符串时会拒绝保存并抛出错误。 无论使用何种SQL模式,向TEXT列插入数据发生截断尾部空格操作时都会产生警告。 对于BLOB和TEXT类型,存储和检索时不会进行填充到指定长度的操作。 如果为TEXT列创建了索引,索引项的比较会填充空格。也就是说,如果索引具有唯一约束,那么仅尾部空格数不同时将会抛出键值冲突错误。例如,一个表中已经存在值’a’,当再保存’a’时就会发生错误,但是该规则对于BLOB不适用。 多数情况下,你可以将BLOB列视为能够足够大的VARBINARY列。同样,你也可以将TEXT列视为VARCHAR列。BLOB和TEXT与VARBINARY和VARCHAR具有以下区别: i:对于BLOB和TEXT列的索引,必须指定索引前缀的长度。对于CHAR和VARCHAR,前缀长度是可选的。 ii:BLOB和TEXT列没有默认值。 如果TEXT列类型使用了BINARY的属性,将为列匹配指定字符集对应的二进制校对规则。 LONG(应该是LONGBLOB,官网文档编辑漏字了?)和LONG VARCHAR对应MEDIUMTEXT数据类型。为了保证兼容性。 MySQL连接器(MySQL Connector /ODBC)将BLOB值定义为LONGVARBINARY,将TEXT值定义为LONGVARCHAR。 由于BLOB和TEXT值可能会非常长,使用它们时可能遇到下面的这些约束: i:当排序时只使用该列的前max_sort_length个字节。max_sort_length的默认值是1024;该值可以在启动mysqld服务器或运行时使用--max_sort_length选项进行更改。任何客户端的修改仅在对应的session下有效:
ii: 应该避免使用”SELECT * …”之类的语句查询出所有的列。因为内存不支持BLOB和TEXT数据类型,在检索时,服务器会在磁盘上而非内存中创建临时表。使用磁盘会带来性能上的损失,所以只在必要时才对BLOB和TEXT类型的列进行检索。 iii: BLOB或TEXT对象的最大大小由其类型决定,但在客户端和服务器之间实际传输的最大值是由可用内存量和通信缓冲区大小决定的。你可以通过修改max_allowed_packet变量的值更改缓冲区的大小,但必须同时修改服务器和客户端。例如,可以使用MySQL和mysqldump修改客户端max_allowed_packet的值。 参考Section 5.1.1, 每个BLOB或TEXT类型的值都由内部分配的对象表示。与其它类型不同,BLOB或TEXT类型在每次打开表时都会为其分配存储引擎。 在某些情况下,可能需要在BLOB或TEXT列中存储媒体文件之类的二进制数据。你可以使用MySQL中字符串处理函数来处理此类数据。出于安全和其他原因,最好使用应用程序代码来做此类处理,而不是给应用程序用户提供文件操作特权。你可以在MySQL的论坛中讨论各种语言和平台的细节(http://forums.mysql.com/)。 |
TEXT与BLOB的区别(引自CSDN#HermanLiu的文章《MySQL下,text 、blob的比较》)
(1)相同
在TEXT或BLOB列的存储或检索过程中,不存在大小写转换,当未运行在严格模式时,如果你为BLOB或TEXT列分配一个超过该列类型的最大长度的值值,值被截取以保证适合。如果截掉的字符不是空格,将会产生一条警告。使用严格SQL模式,会产生错误,并且值将被拒绝而不是截取并给出警告.
BLOB和TEXT列不能有 默认值.
当保存或检索BLOB和TEXT列的值时不删除尾部空格。(这与VARBINARY和VARCHAR列相同).
对于BLOB和TEXT列的索引,必须指定索引前缀的长度。对于CHAR和VARCHAR,前缀长度是可选的.
(2)相异
text:
TEXT值是大小写不敏感的
Text被视为非二进制字符串
TEXT列有一个字符集,并且根据字符集的 校对规则对值进行排序和比较
可以将TEXT列视为VARCHAR列
MySQL连接程序/ODBC将TEXT值定义为LONGVARCHAR
BLOB 可以储存图片,TEXT不行,TEXT只能储存纯文本文件。4个TEXT类型TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT对应于4个BLOB类型,并且有同样的最大长度和存储需求。
blob:
BLOB值的排序和比较以大小写敏感方式执行;
BLOB被视为二进制字符串;
BLOB列没有字符集,并且排序和比较基于列值字节的数值值。
在大多数方面,可以将BLOB列视为能够足够大的VARBINARY列
MySQL连接程序/ODBC将BLOB值定义为LONGVARBINARY
一个BLOB是一个能保存可变数量的数据的二进制的大对象。4个BLOB类型TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB仅仅在他们能保存值的最大长度方面有所不同。
(3)其他:
VARCHAR,BLOB 和TEXT类型是变长类型,对于其存储需求取决于列值的实际长度(在前面的表格中用L表示),而不是取决于类型的最大可能尺寸。例如,一个 VARCHAR(10)列能保存最大长度为10个字符的一个字符串,实际的存储需要是字符串的长度,加上1个字节以记录字符串的长度。对于字符串‘abcd‘,L是4而存储要求是5个字节。
BLOB和TEXT类型需要1,2,3或4个字节来记录列值的长度,这取决于类型的最大可能长度。VARCHAR需要定义大小,有255的最大限制;TEXT则不需要。如果你把一个超过列类型最大长度的值赋给一个BLOB或TEXT列,值被截断以适合它。
CHAR(n) 固定长度,最多 255 个字符
VARCHAR(n) 可变长度,MySQL 4.1 及以前最大 255 字符,MySQL 5 之后最大 65535 字节
TINYTEXT 可变长度,最多 255 个字符
TEXT 可变长度,最多 65535 个字符
MEDIUMTEXT 可变长度,最多 16777215(2^24 - 1)个字符
LONGTEXT 可变长度,最多 4294967295(2^32 - 1)(4G)个字符
ENUM类型
ENUM中文名称叫枚举类型,它的值范围需要在创建表时通过枚举方式显式指定,对1~255个成员的枚举需要一个字节存储;对于255~65535个成员,需要2字节存储。最多允许65535个成员。下面往测试表t中插入几条记录来看看ENUM的使用方法。
(1) 创建测试表
mysql> CREATE TABLE t (sex ENUM(‘M‘,‘F‘)); Query OK, 0 rows affected (0.02 sec) |
(2) 插入4条不同的记录:
mysql> INSERT INTO t VALUES(‘M‘),(‘1‘),(‘f‘),(NULL); Query OK, 4 rows affected (0.01 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM t; +------+ | sex | +------+ | M | | M | | F | | NULL | +------+ 4 rows in set (0.00 sec) |
从上面的例子中,可以看出ENUM类型是忽略大小写的,在存储“M”、“f”时将它们都转换成了大写。
(3) 继续逐个插入记录(1),(2),(3),(‘X’):
mysql> INSERT INTO t VALUES(1); Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO t VALUES(2); Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO t VALUES(3); ERROR 1265 (01000): Data truncated for column ‘sex‘ at row 1 mysql> INSERT INTO t VALUES(‘X‘); ERROR 1265 (01000): Data truncated for column ‘sex‘ at row 1 |
发现在插入数值(3)和字符(‘X’)时,报错了。
测试结果并不像有些资料中说的“超出枚举范围时会自动取值第一个”。看官方对该部分的说明:
每个枚举值都有自己的索引值:
该索引值表示枚举元素在定义时的位置,从1开始;
NULL值的索引值是NULL;
这里的“索引”是指枚举元素在列表中的位置,与数据库中的“索引”概念无关。
可以使用SELECTenum_col_name + 0 FROM table_name;查看列中保存了列表中哪个位置的值。
另外,ENUM类型只允许从值集合中选取单个值,而不能一次取多个值。
SET类型
SET和ENUM类型非常类似,也是一个字符串对象,里面可以包含0~64个成员。根据成员的不同,存储上也有所不同。
集合成员数 |
所占字节 |
1~8 |
1 |
9~16 |
2 |
17~24 |
3 |
25~32 |
4 |
33~64 |
8 |
SET和ENUM除了存储之外,最主要的区别在于SET类型一次可以选取多个成员,而ENUM则只能选一个。如:
mysql> CREATE TABLE t (s SET(‘a‘,‘b‘,‘c‘,‘d‘)); Query OK, 0 rows affected (0.03 sec) mysql> INSERT INTO t VALUES(‘a,b‘),(‘a,d,a‘),(‘a,c‘),(‘a‘),(‘a,a,a‘); Query OK, 5 rows affected (0.01 sec) Records: 5 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM t; +------+ | s | +------+ | a,b | | a,d | | a,c | | a | | a | +------+ 5 rows in set (0.00 sec) |
SET类型可以从允许值集合中选择任意1个或多个元素进行组合,所以对于输入的值只要是在允许值的范围内,都可以正确地注入到SET类型的列中。对于超出允许范围的值例如(‘a,d,f’)将不允许保存,而对于(‘a,a,a’)这样包含重复成员的集合将只取一次。