int(10)和int(11)到底有什么差别???

2018-09-06 12:07:41 Linux 阅读 (4311) 评论(0)

        项目开发时,需要先行设计数据库。不得不说,做程序开发这一行,经验实在太重要了,所以在设计数据库时,大多数人是凭经验去设定数据表各个字段的数据类型,比如主键id一般为int(10) unsigned primary key, 也有的是为int(11) unsigned primary key。这样问题就来了,为什么是选择int(10),有的选择int(11)?是有什么客观条件约束,抑或是“之前都是这么设计的“?int(10),int(11)也困扰了我好久,现在就来再次研究一下这其中的区别。


    1. 先介绍下MySQL的int类型相关数据类型

         (1). mysql数据库中对整型分为5个不同的小类型,分别是tinyint、smallint、mediumint、int和bigint,主要区别是数据库存储时使用几个字节,也就是说限定整数的范围,上述类型存储使用的字节为1、2、3、4和8。取值范围可以根据字节数来算出来。注意:它们都可以指定为无符号(大于等于零)的整数。

类型
字节数最小值(有符号)最大值(有符号)最小值(无符号)最大值(无符号)
tinyint1-1281270255
smallint2-3276832767065535
mediumint3-83886088388607016777215
int4-2147483648214748364704294967295
bigint8-922337203685477580892233720368547758070

18446744073709551615

       (2). 不同的数据类型的所占用的字节数是不同的,而一个字节包含8个byte(二进制位:0,1),所以也就是说tinyint由  1个字节数 * 8个byte = 8个二进制位   组成,所以这8个二进制位能表示的数值的范围就是tinyint其所能存储的值的范围。

       (3). 再比如说,int类型占4个字节,就是32个byte,

                    有符号时: -2^31 (-2,147,483,648) 到 2^31 – 1 (2,147,483,647) 

                    无符号时:0到2^32(4294967295)

       (4). 二进制有符号位和无符号的差别在于:第一位表示正负, 第一位是0表示是正数,1表示是负数

            无符号数: 1111 1111    值:255,

                1* 2^7 + 1* 2^6 + 1* 2^5 + 1* 2^4 + 1* 2^3 + 1* 2^2 + 1* 2^1 + 1* 2^0 = 255

            有符号数: 0111 1111    值:127      ,有符号位时,第一位不参与运算,只表示正负   

                1* 2^6 + 1* 2^5 + 1* 2^4 + 1* 2^3 + 1* 2^2 + 1* 2^1 + 1* 2^0 = 127


            对于给定一个二进制数,无法判断是有符号还是无符号,有符号无符号是人为指定的,就如mysql中给可以明确指定字段类型是不是有符号无符号(unsigned),设定好,在根据有无符号位,做相应的逻辑处理。


    2.重点来了,int(10),int(11)的区别在哪儿呢?

        上面已经说了,int类型占4个字节,32个byte,其能存储的数值范围已经是确定了的了!!!

        也就是说不管int(10),int(11),这个点类型已经定了是int,其存储范围是完完全全相同的!!!

        那int(10),int(11)括号里的又数字表示什么呢?    答:显示宽度,

        那什么是显示宽度呢?请继续往下看

        说再多,不如一个demo来的实在:

        

        这里我用Navicat新建一个test1表,包含2个字段a tinyint(1), b tinyint(3),并且插入两条数据

    image.pngimage.png

    

    然后,我们去查询这两条数据,我这里直接用的yii框架。里面的bin是mysql自带的函数,mysql的bin()函数能计算出这个值原始存储的二进制数。

image.png

    查询结果如下:

    一切正常,bin(a),bin(b)也是a,b的二进制数

image.png

    然后修改下刚才的表结构,字段b还是tinyint(3),不过下面的填充零点上,既是tinyint(3) zerofill,然后在看下查询数据
image.png             image.png


        上面的查询结果,已经能看出些不同了,在设定字段b填充零后,查出来的结果与之前就发生了变化,之前是‘1’变成了‘001’,之前是‘12’就变成了‘012’,这里我们就再说一下显示宽度这个概念,显示宽度只有和字段有zerofill这个属性结合起来才有意义。

        这样说,字段b为tinyint(3),显示宽度为3位,如果没有zerofill,没什么影响,如果有了zerofill就有了变化。当存储的数据长度未达到字段设定的显示宽度(这里是3),mysql就会自动的在数据的左侧填充 0,已达到设定的显示宽度,所以说,原来的数值 1,长度只有1位,没有达到设定的显示宽度3,所以mysql自动将其填充为‘001’,但是其原始存储的二进制数据,没有任何变化,这只是‘应用层’的一个处理。这样说,应该能明白显示宽度了吧。

        再说一下int(10)和int(11) 的问题,很多时候程序开发是为了解决极值(边界)问题,上面已经说到无符号位int最大存储值是 42 9496 7295(42亿多,数字是10位),一般情况下设计数据表时,主键id一般都会设为int,但是int最大为42亿多,我们不去怀疑有的很大型的项目,可能会达到这么大的数据量,但是更多的项目根本达不到这个数据量,可能连mediumint(1677 7215,1千6百多万)都达不到,但是“经验”告诉我们还是要设为 int

        int(10)或int(11)显示宽度都已经能涵盖了int整个取值范围了,如果没有zerofill,就基本上没有任何差别了,如果有的话,就会自动填充到显示宽度,不过这样的话,int(10)只有10亿(10位数字)考上的不会发生填充0情况,int(11)所有的都会发生填充0 的情况(毕竟int最多也就10位数字)。不过呢,在数据库表的设计中一般不会给字段设定填充0的(起码,我没这样设计过)。

    


    All of the above, int(10),int(11)只是一个显示宽度的问题,其所能存储的范围是一样的。如果字段没设定zerofill的话,没有任何差别!

    That's it!

    

    


评论