在一开始接触MySQL数据库时,对于int(M)及tinyint(M)两者数值类型后面的M值理解是最多能够插入数据库中的值不能大于M;
后来工作后,也是一边学习一边使用,之后的理解是其中的M的意思是插入数据库中的值的字符长度不能大于M,例如,int(4),想要插入1234,1234的字符长度是4,就正好可以插入数据库,12341就不行,因为是5个字符长度,这也都是道听途说,自己从来没有验证过;
如今,由于面试中经常会被问到有关数据库方面的知识,今天也想着深入了解下这个M代表的含义(上述两个理解都是错误的)。
首先,创建一个数据表test:
mysql> CREATE TABLE test(
-> id1 int(1),
-> id2 tinyint(1)
->);
我们给id1定义为int,并设置字符长度为1,id2定义为tinyint,也设置字符长度为1;
然后分别插入值127,127,结果发现,两者都插入到了数据表中:
mysql> INSERT INTO test(id1,id2) values(127,127);//运行成功
结果是插入成功的,从此次测试已经可以知道,我之前的想法都是错误的,接下来我们再做一个实验,插入数据128,128,即id=128,id2=128:
mysql> INSERT INTO test(id1,id2) values(128,128);//运行失败:ERROR 1264 (22003):Out of range value for column 'id2' at row 1
出错了,int类型的id1插入成功了,tinyint类型的id2提示超出了范围,这是为什么呢?
首先,我们先要了解一个基础知识点,就是下面这张表:(摘自W3C教程)
上述表格中的数值类型都是定长的,也就是说,无论你存的数值是多少,多大或者多小,占用的字节大小都是固定的。例如,之前设置的int(1),虽然M值是1个字符,但是它所占用的空间大小永远都是4个字节的大小,换句话说就是,你可以存入有符号整型从-2 147 483 648到2 147 483 647包括这两个数的中间任何一个数。int(1)和int(11)占用的是4个字节,可以存入上述这些数,tinyint(1)和tinyint(4)占用的是1个字节,可以存入从-128到127的数,这也是为什么之前的一次试验,int(1)插入128成功,而tinyint(1)插入128却提示超出长度。
那么,这个M值到底代表什么意思呢?
到这里,我们已经可以发现,M值即使设置为1,它也可以存入字符长度大于1的值,那么,如果存入的字符长度小于1会怎么样?我们来试一试:
先将id1的类型更改为int(2),然后插入数据id1=1:
mysql> ALTER TABLE test Modify id1 int(2);
mysql> INSERT INTO test(id1) values(1);//运行成功,说明值1已经插入到test表中
我们查询一下表中的数据,看看结果具体如何:
mysql> SELECT * FROM test;
+------+
| id1 |
+------+
| 1 |
+------+
接下来,我们再修改一下id1的填充数据类型zerofill(表示用0填充),这里先知道如何操作即可,我们再从结果得出结论:
mysql> ALTER TABLE test MODIFY id1 int(2) zerofill;
mysql> SELECT * FROM test;
+------+
| id1 |
+------+
| 01 |
+------+
现在是不是有些清楚了。我们设置的M值是2,没有设置zerofill用0填充时,对于操作没有任何影响,而设置了zerofill后,我们可以清楚地看到值1字符数不足M值,左前位置补0。我们也可以将M值设置成别的大小进行多次测试,这里就不进行测试了。
需要强调的是,不同的数据类型中的M值意义是不一样的,我们这里仅讨论整型中的M值。
从上面我们可以得到如下的结论:
1、整数型的数值类型已经限制了取值范围,有符号整型和无符号整型都有,而M值并不代表可以存储的数值字符长度,它代表的是数据在显示时显示的最小长度;
2、当存储的字符长度超过M值时,没有任何的影响,只要不超过数值类型限制的范围;
3、当存储的字符长度小于M值时,只有在设置了zerofill用0来填充,才能够看到效果,换句话就是说,没有zerofill,M值就是无用的。
总结:int(11),tinyint(1),bigint(20),后面的数字,不代表占用空间容量。而代表最小显示位数。这个东西基本没有意义,除非你对字段指定zerofill。
所以我们在设计mysql数据库时,建表时,mysql会自动分配长度:int(11)、tinyint(4)、smallint(6)、mediumint(9)、bigint(20)。
所以,就用这些默认的显示长度就可以了。不用再去自己填长度,比如搞个int(10)、tinyint(1)之类的,基本没用。而且导致表的字段类型多样化。