美文网首页MySQL
MySQL知多少--数值类型

MySQL知多少--数值类型

作者: 逅弈 | 来源:发表于2018-03-16 10:24 被阅读27次

    mysql是我们常用的数据库,因为他开源、免费、社区活跃等等。基于mysql可以构建出非常庞大的数据库集群。对于程序员来说,虽然不需要达到专业DBA的要求,但是mysql基本的使用,怎样使用能最大化mysql的性能还是需要掌握的。
    作为程序员,我们需要了解并熟悉以下但不限于以下几点内容:

    • mysql常用的数据类型
    • mysql常用的存储引擎
    • mysql不同的索引的实现方式
    • 怎样创建高性能的索引
    • 使用explain分析、优化sql语句

    本文让我们了解下mysql常用的数据类型。
    一般我们常用的数据类型就是数值型和字符型两种,其他的像日期、时间类型可以转换成数值来保存,ip也可以转成数值,那我们就来详细了解下这两种类型吧。

    数值类型

    数值类型又可以分为整数实数,整数和实数的区别之一是整数是不带小数的。
    根据整数类型所占的空间,可以分为:TINYINTSMALLINTMEDIUMINTINTEGERBIGINT
    他们分别占用的空间是:

    类 型 所占空间 最小值 最大值
    TINYINT 1字节 -2^7 2^7-1
    SMALLINT 2字节 -2^15 2^15-1
    MEDIUMINT 3字节 -2^23 2^23-1
    INTEGER 4字节 -2^31 2^31-1
    BIGINT 8字节 -2^63 2^63-1

    以上的最小最大值的范围是包括负数的,也可以指定创建无符号(unsigned)的整数,如果指定了无符号,那么最小值将变为0,最大值将变为2^N-1 ,这里的N表示整数类型存储空间所占的位数。我们知道数据在计算机中最终是以位(bit)来存储的,一个bit可以表示0和1两种情况。1个字节(byte)占8个位,那一个8位无符号的数字,最大值为2^8-1,因为无符号的话,最高位也用来表示数值,所以可以表示的正数的个数就扩大了一倍。

    举个例子

    我们拿int来举例,我们通常创建表的时候一般会创建一个int(11)并且是自增的id字段作为表的主键。那这里的int就是整数类型中占4个字节的INTEGER了,范围是[-2^63 , 2^63-1]。那int括号里面的11是干吗用的呢?括号中的值叫做显示宽度。当实际存储的数值的长度小于显示宽度时,查询的结果显示时左侧将用空格补全,如果设置了ZEROFILL属性的话,将会用0来补全。具体是什么意思呢,我来举个例子。
    比如我有一个int(4)的字段:电话区号tele_code。
    常州的区号是0519:
    存储在数据库中为[519],查询时展示为[ 519],5前面有一个空格填充,如果设置了ZEROFILL属性的话,则查询时展示为[0519]
    同理南京的区号是025:
    存储在数据库中为[25],查询时展示为[ 25],2前面有两个空格填充,如果设置了ZEROFILL属性的话,则查询时展示为[0025]

    需要注意的是,当为一个字段设置了ZEROFILL属性的话,mysql会自动将该字段设置为unsigned

    PS:这个例子举的并不好,因为区号0250519这前面的0是内容的一部分,是需要保留的,而用int来存的话,左侧的0实际是被丢弃了,所以对于这种场景还是用字符型来存储比较好。

    存储数值范围

    那看到这里,就引出来一个问题,这个int(4)能存储超过4位长度的整数吗,比如10000?答案是可以的。要搞清楚这个问题,还是要了解清楚上面表格中的最小值最大值的含义。每个整数类型能存储的数值的最小和最大值跟该类型存储所占的位数有关,跟括号里面的4(也就是显示宽度)没有关系。那int类型的最大值为2^31-1=2147483647,那肯定能保存10000啊。
    那有心的小伙伴可能就发现了,要存储电话区号,完全可以用SMALLINT来存。因为SMALLINT占16位,最大值为32767,而电话区号是4位数字,最大的4位数字也不过9999,所以完全可以用smallint(4)来存储了。

    显示宽度

    说到这里,我们就知道了,其实保存整数的范围只与整数的类型有关。根据mysql手册,显示宽度的最大值为255。为什么是255呢?难道是因为这个显示宽度的值需要用一个字节来保存?一个字节占8位,2^8-1=255,如果是这样的话那就说得通了。
    那我们定义int(1)和int(11)就没有区别了吗?正常是没有区别的,能存进int(11)中的值,也照样能存进int(1)中。
    那如果存储的数值超过了字段的显示宽度,那会怎么样呢?mysql手册中关于存储数值的长度超过显示范围的就一句话:
    The ZEROFILL attribute is ignored when a column is involved in expressions or UNION queries.
    If you store values larger than the display width in an integer column that has the ZEROFILL attribute, you may experience problems when MySQL generates temporary tables for some complicated joins. In these cases, MySQL assumes that the data values fit within the column display width.

    翻译成中文就是:
    如果你在一个整型列(使用了ZEROFILL属性)存储了超过显示宽度的更大值,当MySQL对于某些复杂的联结(join)生成临时表时,你可能会遇到问题,因为在这些情况下,MySQL相信数据确实适合原来的列宽度。

    那看到这里又有问题了,谁会没事定义一个int(255) zerofill类型的字段啊?另外,既然这个显示宽度跟字段可存储的数值范围没关系,那为什么要设计这个显示宽度呢?
    其实从以下几个方面来看待这个显示宽度,我们就不会那么纠结了:

    • 记住最重要的一点:显示宽度并不是用来指定存储空间或者数字长度的。他只是用来告诉mysql,返回这一列的值时该怎样格式化字段中的内容。记住int(5)同样能存储int(6)或int(255)能存储的数值。但是int(255)并不能存储一个长度为255的数值,具体能存储多大的数值(多大的数值决定了数字的最大长度)是由INT所占的存储空间决定的
    • 如果在一个有显示宽度的字段上使用了ZEROFILL 属性,并且存储的数值的字符表现形式的长度小于他的显示宽度,那么返回时左侧将以0补全。例如,在一个int(5)上存储123,那将会返回00123,如果存储的是12345,那返回的也将会是12345
    • 如果在整数字段上使用了ZEROFILL属性,那么该字段会自动加上UNSIGNED属性

    实际操作一下

    为了更好的了解这个问题,让我来创建一张表测试一下。
    创建一张表:test_a

    CREATE TABLE `test_a` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `aid` int(1) NOT NULL,
      `bid` int(10) zerofill NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB;
    
    img1.png

    插入几条测试数据:

    insert into test_a (aid,bid)
    values 
    (1,2),
    (111,222);
    
    img2.png

    执行一下查询:

    select * from test_a;
    

    返回的结果如下:


    img3.png

    可以看到,查询出的bid这一列的值,不足10个显示宽度的在左侧用0做了补全。
    aid这一列虽然显示宽度是1,但是仍然可以存储超过1个长度的值,并且显示也没有问题。

    好了今天写的有点晚了,下一篇让我们来了解下mysql的字符类型。

    我是逅弈,如果文章对您有帮助,欢迎您点赞加关注,并欢迎您关注我的公众号:

    欢迎关注微信公众号

    相关文章

      网友评论

        本文标题:MySQL知多少--数值类型

        本文链接:https://www.haomeiwen.com/subject/xjdkqftx.html