查看原文
其他

不要再被MYSQL的INT(M)给迷惑了

曲健Nicholas 曲水流觞TechRill 2020-02-06

MYSQL里有些比较隐晦的知识点,经常被稀里糊涂的用错而不自知。以前评审过程发生的次数较多,索性随手写一些出来。前人栽个树,后人一定要乘凉啊!

表设计使用整型时,经常发现定义int括号里的M是五花八门的。误区是,不少人把M当成了数据库中存储的最大长度,而实际上这个代表的是显示宽度。只要是int类型,在数据库里的存储就一定是4个字节。


有符号整型:从-2^31(-2147483648) 到 2^31-1(2147483647)

无符号整型:从 0 到 2^32(4294967295)


那么这个M显示宽度到底怎么理解?这里先说个属性 zerofill(零填充)。因为只有用了这个属性,显示宽度才有存在的意义。


zerofill的作用说明

1. 当一个数值列类型被定义成zerofill时,查询此列MYSQL会自动在数值左侧填充0直到M长度,若数值长度已超过M, 则无需填充0;

2. 声明为zerofill的数值列,默认会自动加上 unsigned(无符号) 属性。这个很容易理解,在一个负号前填充0是没什么意义的。

上例子。

Step 1 >

创建一张测试表,都是整型列,M分别定义为0,1,6,11,15。后缀为“z”的列被声明为zerofill。

细心的人可以发现:

- 没有标注unsigned的zerofill列,在表创建完成之后也会自动加上unsigned

- M为0的整型列,有符号自动定义为11,无符号自动定义为10


Step 2 >

插入测试数据100,10000000(8位),2147483647(有符号整型最大值),4294967295(无符号整型最大值), 9223372036854775807(有符号BIGINT最大值)。


Step 3 >

运行select查询全部数据。


Step 4 >

简单解读一下:

- 不管M定义多长,INT可存储的数值范围都由 4个字节 和 有无符号 来决定;

- 超过最大值不报错,直接存储最大值;

- 基于M显示宽度值来左填充0,只有声明zerofill的列才可以产生效果;


重申 >

若觉得使用int有点浪费,比如状态列,那可以使用tinyint, 千万不要想当然的以为int(1)存的是就一位数字,还沾沾自喜的觉得节省了存储空间。


题外话

To be honest,MYSQL这个设计个人感觉是个失败品。不少人建议过应该取缔它,不管用LPAD()还是换成CHAR都可以实现这个功能,且不会产生歧义。日常编码也建议使用后面这两者。

推荐阅读

1. MYSQL基础知识及案例分析

2. 不懂NOSQL这些知识, 怎么吹牛B

3. 30分钟入门图数据库(精编版)

4. 图数据库OrientDB-基础篇

5. OrientDB实战进阶 - RBAC案例

6. OrientDB进阶 - 分布式架构


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存