MySql中int类型的简单总结
问题
首先问两个问题:
- int(1)和int(10)有什么区别。
- int(3)可以存储 10000 这个数字吗?
- int(11)可以用来存储手机号么?
本次的源代码以及测试的 Mysql 版本均为 8.0.17
解释
首先新建一个表,SQL如下:
1 | create table test_int( |
当你执行完这个 SQL 以后,Mysql会发出一个如下提示:
[2019-12-16 23:08:24] [HY000][1681] Integer display width is deprecated and will be removed in a future release.
首先不管这个提示,待会后文会解释的。
然后新增测试数据:
1
2INSERT INTO `test`.`test_int` (`id`, `no`, `phone`) VALUES (10000, 1008611, 123124);
INSERT INTO `test`.`test_int` (`id`, `no`, `phone`) VALUES (10, 134, 124);
然后再进行 select 查看。
1
2
3
4
5
6
7
8 mysql> select * from test_int;
+-------+---------+--------+
| id | no | phone |
+-------+---------+--------+
| 10 | 134 | 124 |
| 10000 | 1008611 | 123124 |
+-------+---------+--------+
2 rows in set (0.00 sec)
可以看到其实并没有影响到任何数据的插入,随后查询 Mysql 的官方文档,里面有这样的一段话
If you specify ZEROFILL for a numeric column, MySQL automatically adds the UNSIGNED attribute to the column.
随后再次新建一个表:
1 | create table test_int_zerofill( |
虽然提示 ZEROFILL 快要被废弃了,但是为了演示区别,所以暂时还是不管了。
1 | mysql> select * from test_int_zerofill; |
所以对于问题1,所以 int(1) 和 int(10) 其实是没有区别的,唯一有区别的地方就在于如果使用了 unsigned zerofill
修饰的话,那么不足长度的会在左边进行补 0 ,而如果没有用 unsigned zerofill
进行修饰的话,可以说基本上是没有区别的。
对于问题2,因为 int 括号里面的值与位数无关, 所以是可以的。
到此,对于执行第一个SQL所进行的提示,是因为 Mysql 也觉得其实没什么意义,而是更加推荐用 LDAP()
这个函数来判断。
对于第二个问题,可以尝试一个手机号:
1 | INSERT INTO `test`.`test_int_zerofill` (`id`, `no`, `phone`) VALUES (10, 10, 13100000000) |
出现这个问题的原因在于 int 类型在 mysql 里面是四个字节,而一个字节是 8 位,所以在 mysql 里面,一个int 类型最多可以储存 2^31(一个符号位置),也就是约 21 亿左右,无符号的也最多42亿,但是手机号最低也是11位,也就是 130 多亿。所以肯定是无法存储的。
下面是 Mysql 官方给出的 num 类型的存储范围
源码
由于想看下 Mysql 到底是如何处理 int 类型的数值的,于是下载并且编译了 Mysql 的源码,一直跟着 debug,最后找到了 Mysql 判断 int 是否超长的一个代码,如下:
1 | type_conversion_status Field_long::store(double nr) { |
在这段代码里面,Mysql首先会判断是否带有符号位,如果是无符号位的话,则是直接判断是否大于 UINT_MAX32,而如果是有符号的话,则是判断是否小于 INT_MIN32 或者大于 INT_MAX32,否则直接为最小或者最大值,然后设置error。
PS:这一段代码是还未进行 InnoDB 引擎层,可以看到 Mysql 是在 Server 层进行SQL语句的校验。
MySql中int类型的简单总结