一.问题
一直以为int(M) 中M代表只能存储M个字符的数据,比如int(2),只能存储0-99 ,偶然发现这是错误的想法
二.实验
1.新建表
create table testInt(
id1 int(1),
id2 tinyint(1)
);
INSERT INTO testInt(id1,id2) values(127,127); -- 运行成功
从结果来看,问题中的想法确实错误
INSERT INTO testInt(id1,id2) values(128,128);
-- error 1264 - Out of range value for column 'id2' at row 1
出错了,int类型的id1插入成功了,tinyint类型的id2提示超出了范围,这是为什么呢?下面看一张表
上述表格中的数值类型都是定长的,也就是说,无论你存的数值是多少,多大或者多小,占用的字节大小都是固定的。
到这里,我们已经可以发现,M值即使设置为1,它也可以存入字符长度大于1的值,那么,如果存入的字符长度小于1会怎么样?我们来试一试:
先将id1的类型更改为int(2),然后插入数据id1=1
ALTER TABLE testInt Modify id1 int(2);
INSERT INTO testInt(id1) values(1);
-- 运行成功
我们查询一下表中的数据,看看结果具体如何:
mysql> select * from testInt;
+-----+------+
| id1 | id2 |
+-----+------+
| 1 | NULL |
+-----+------+
2 rows in set (0.07 sec)
接下来,我们再修改一下id1的填充数据类型zerofill(表示用0填充),这里先知道如何操作即可,我们再从结果得出结论:
提示:命令行查询才会显示01,navicat工具查询只会显示1
mysql> ALTER TABLE testInt MODIFY id1 int(2) zerofill;
mysql> select * from testInt;
+-----+------+
| id1 | id2 |
+-----+------+
| 01 | NULL |
+-----+------+
现在是不是有些清楚了。我们设置的M值是2,没有设置zerofill用0填充时,对于操作没有任何影响,而设置了zerofill后,我们可以清楚地看到值1字符数不足M值,左前位置补0
三.结论
从上面我们可以得到如下的结论:
1、整数型的数值类型已经限制了取值范围,有符号整型和无符号整型都有,而M值并不代表可以存储的数值字符长度,它代表的是数据在显示时显示的最小长度;
2、当存储的字符长度超过M值时,没有任何的影响,只要不超过数值类型限制的范围;
3、当存储的字符长度小于M值时,只有在设置了zerofill用0来填充,才能够看到效果,换句话就是说,没有zerofill,M值就是无用的。
四.补充
char(M)是一种固定长度的类型,varchar(M)则是一种可变长度的类型,超过M的字符将会被截掉,m必须小于该类型允许的最大字符数。
CREATE TABLE `testChar` (
`id1` varchar(2) DEFAULT NULL,
`id2` char(2) DEFAULT NULL
);
mysql> insert into testInt values('12','122');
1406 - Data too long for column 'id2' at row 1
它们的区别是:
char(M)类型的数据列里,每个值都占用M个字节,如果某个长度小于M,MySQL就会在它的右边用空格字符补足.(在检索操作中那些填补出来的空格字符将被去掉)
在varchar(M)类型的数据列里,每个值只占用刚好够用的字节再加上一个用来记录其长度的字节(即总长度为M+1字节).