所谓的数据类型:对数据进行统一的分类。从系统的角度出发为了能够使用统一的方式进行管理,以便更好的利用有限的资源空间。
SQL将数据分为了三大类:数值类型、字符串类型和时间日期型。
如下图所示:
其中数值类型分为整数型和小数型。
【1】整数型
① 有符号
CREATE TABLE `my_int` ( `int_1` tinyint(4) DEFAULT NULL, `int_2` smallint(6) DEFAULT NULL, `int_3` mediumint(9) DEFAULT NULL, `int_4` int(11) DEFAULT NULL, `int_5` bigint(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8
插入最大范围值
insert into my_int VALUES(127,32767,8388607,2147483647,9223372036854775807);
② 无符号
CREATE TABLE `my_int_unsigned` ( `int_1` tinyint(3) unsigned DEFAULT NULL, `int_2` smallint(5) unsigned DEFAULT NULL, `int_3` mediumint(8) unsigned DEFAULT NULL, `int_4` int(10) unsigned DEFAULT NULL, `int_5` bigint(20) unsigned DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入最大范围值
insert into my_int_unsigned VALUES(255,65535,16777215,4294967295,18446744073709551615);
③ 显示宽度
数据类型中int (10) 或者数据表中的长度:这表示的是该数据类型指定的显示宽度,指定能够显示的数值中数字的个数。(有符号时,负号占一位,正数不计符号位)。
显示宽度和数据类型的取值范围是无关的。
显示宽度只是指明MYSQL最大可能显示的数字个数,数值的位数小于指定的宽度时会有零填充(使用了zerofill),如果插入了大于显示宽度的值,只要该值不超过该类型整数的取值范围,数值依然可以插入,而且能显示出来。
假设声明一个INT类型的字段 YEAR INT(4) ,该声明指明,在year字段中的数据一般只显示4位数字的宽度。
例如,向year字段插入一个数值19999,当使用select查询的时候,MYSQL显示的将是完整带有5位数字的19999,而不是4位数字的值。如果不指定显示宽度,则MYSQL为每一种类型指定默认的宽度值
再次强调显示宽度只用于显示,并不能限制取值范围和占用空间,例如:INT(3)会占用4个字节的存储空间,并且允许的最大值也不会是999,而是INT整型所允许的最大值。
那么疑问就来了,这个有什么意义?往下看。
④ 零填充zerofill
zerofill:零填充;当插入数据长度不够表结构中的字段长度时,左边使用零进行填充。zerofill会自动将字段类型设置为无符号。
ALTER TABLE my_int_unsigned MODIFY int_6 TINYINT(3) ZEROFILL; --表示显示宽度为三,当不够时,使用0填充;超出时,只要不超出数据类型最大值,仍正常显示。 desc my_int_unsigned;
INSERT into my_int_unsigned VALUES(100,100,100,100,100,1); SELECT * FROM my_int_unsigned
可见,意义在于使用了zerofill时,长度不足时左侧会自动补零。保证了数据的格式化,如select下拉框不会因为数值长度而改变宽度。
但是当不使用zerofill时,显示宽度的指定没有意义,使用默认值即可。
在navicat for mysql工具下未显示区别。
【2】小数型
小数型:带有小数点或范围超出整型的数值类型;SQL中又将小数型分为浮点型和定点型。
- 浮点型:小数点浮动,精度有限,超出指定范围后会丢失精度(自动四舍五入);
- 定点型:小数点固定,精度固定,不会丢失精度。
① 浮点型
浮点型数据分为float和double。
- ① Float:单精度,占用 4 个字节存储数据,精度范围为 7 位左右;
- ② Double:双精度,占用 8 个字节存储数据,精度范围为 15 位左右。
create table my_float( f1 FLOAT, f2 float(10,2),--10位在精度范围之外 f3 float(6,2)--6位在精度范围之内 )charset utf8; desc my_float;
插入数据,可以是小数,也可以是科学计数法。整型部分不能超出长度,小数部分可以,系统会自动进行四舍五入。
insert into my_float VALUES(1000.10,1000.10,1000.10); insert into my_float VALUES(1234567890,12345678.90,1234.56); insert into my_float VALUES(3e38,3.01e7,1234.56); insert into my_float VALUES(9999999999,99999999.99,9999.99);
可以看到,float保证精度范围在7位左右,使第二,第四行数据分别发生了进位。甚至第四行前两列数值由于进位变成了 11 位有效数字!!!9999.99由于在精度范围内,故未发生进位 !
insert into my_float VALUES(123456,1234.12345678,123.9876543);--小数部分超出 insert into my_float VALUES(123456,1234.12,12345.56);--整数部分超出
可以看到,小数部分超出会自动截取;整数部分超出则插入失败!!
**结论:**浮点数一定会进行四舍五入(超出精度范围);浮点数如果是因为系统进位导致整数部分超出指定的长度,那么系统也允许成立!
即,如果数据比较大,且有小数点要求精度准备,浮点数不是一个优良选择!!!
② 定点型
定点型:绝对的保证整数部分不会被四舍五入(不会丢失精度),小数部分你有可能(理论上小数部分也不会丢失精度)。
插入数据
定点数的整数部分一定不能超出长度(即使是系统进位造成的也不可以),小数部分的长度可以随意超出(系统自动四舍五入)。
create table my_decimal( f1 float(10,2), d1 decimal(10,2) )charset utf8; desc my_decimal;
insert into my_decimal values(12345678.90,12345678.90); insert into my_decimal values(1234.123456,1234.123456); --小数部分超出长度,会自动四舍五入 select * from my_decimal;
如果系统进位导致长度超出呢?
insert into my_decimal values(99999999.99,99999999.99);--浮点数进位,定点数正常; insert into my_decimal values(99999999.99,99999999.999);--二者都会发生进位,但是定点数会报出异常
select * from my_decimal