MySQL 中的INT(3)和INT(11)究竟差在哪?真相出人意料!

118 阅读6分钟

原文链接

你是不是也曾经在创建数据库表时,对着 INT(3)INT(11) 这样的类型定义犹豫过?心里可能在想:

INT(11) 是不是比 INT(3) 能存更大的数字?”
“是不是 INT(3) 更省空间?”
“这个括号里的数字到底啥意思?🤔”

别担心,你不是一个人!很多刚开始接触 MySQL 的朋友都有过这种困惑。今天,我们就来彻底揭秘这个“括号里的数字”的真实身份,答案可能会让你大跌眼镜!

核心结论抢先看:

INT(3) 和 INT(11) 在存储空间、能存的数字大小范围上,完!全!一!样!

那个括号里的数字 (3 或 11),仅仅是个 “显示宽度” 的提示,而且只在特定情况下才起作用!

是不是感觉有点意外?别急,我们慢慢道来。

一、深入本质:INT 的“硬实力”是固定的

  • • 存储空间: 无论你写 INT(1)INT(3)INT(11) 还是 INT(100),在数据库硬盘上,它们都稳稳地占据着 4个字节 的空间。就像一个小盒子,尺寸是固定的。
  • • 数字范围: 这个固定的“盒子”能装下的数字大小也是固定的:
    • • 有符号整数(可正可负): 从 -2,147,483,648 到 2,147,483,647 (大约 -21亿 到 +21亿)。
    • • 无符号整数(只存正数): 从 0 到 4,294,967,295 (大约 0 到 42亿)。

划重点: INT(3) 和 INT(11) 的“盒子”大小和容量完全一致!INT(3) 绝对能存下 123456 这样的大数,INT(11) 也绝不会比 INT(3) 能存更大的数!

二、括号里的数字 (M):神秘的“显示宽度”

既然存储都一样,那 (3) 和 (11) 的区别到底在哪?答案就在 “显示宽度” (Display Width) 这个概念上。

  • • 它是什么? 你可以把它想象成一个 “建议的显示位数” 或者 “格式化提示”
  • • 它有什么用? 主要用在 ZEROFILL 属性上! 这是关键!

场景实验:当 ZEROFILL 出场时

假设我们创建这样一张表:

CREATE TABLE test_numbers (
    small_display INT(3) ZEROFILL,  -- 显示宽度为3,启用零填充
    large_display INT(11) ZEROFILL  -- 显示宽度为11,启用零填充
);

现在,我们插入一些数字:

INSERT INTO test_numbers (small_display, large_display) VALUES
(55),
(4242),
(123123),
(12341234); -- 注意:1234 超过了 small_display 的显示宽度 3

神奇的事情发生了!查询一下 (SELECT * FROM test_numbers;):

small_displaylarge_display
00500000000005
04200000000042
12300000000123
123400000001234

发生了什么?

  1. 1. ZEROFILL 的作用: 当字段启用了 ZEROFILL,MySQL 在显示这个整数值时,如果数字本身的位数 小于 括号里指定的显示宽度 (M),它会在数字的左边用 0 填充,直到达到指定的宽度。
    • • small_display INT(3) ZEROFILL:显示宽度是 3。
      • • 存 5 (1位数) -> 显示 005 (左边补两个0)
      • • 存 42 (2位数) -> 显示 042 (左边补一个0)
      • • 存 123 (3位数) -> 显示 123 (刚好,不用补)
      • • 存 1234 (4位数) -> 显示 1234 (超出宽度?照样显示!不截断!不报错!)
    • • large_display INT(11) ZEROFILL:显示宽度是 11。
      • • 存 5 -> 显示 00000000005 (左边补10个0)
      • • 存 1234 -> 显示 00000001234 (左边补7个0)
  2. 2. 关键结论:
    • • 括号里的数字 M (3 或 11只在 ZEROFILL 启用时影响显示效果(左边补零)
    • • 它绝不限制你能存储的数字大小! INT(3) 的字段存 123456 完全没问题,显示时如果没有 ZEROFILL 就是 123456,有 ZEROFILL 就是 123456 (因为123456 > 3位,不补零)。
    • • 它也不节省任何存储空间!补零只是在查询结果显示时做的格式化,硬盘上存的还是原始数字 5421231234

三、重要注意事项 & 现代实践

  1. 1. ZEROFILL 的副作用: 一旦给字段加上了 ZEROFILL,MySQL 会自动把这个字段变成 UNSIGNED(无符号整数,只能存非负数)。如果你试图存负数进去,会报错。
  2. 2. MySQL 8.0+ 的弃用:  ZEROFILL 属性在 MySQL 8.0 版本已被标记为 废弃 (Deprecated)  官方不推荐在新项目中使用它,未来版本可能会移除。主要原因是这种格式化显示的工作,更适合放在应用程序层面(比如你的 PHP, Python, Java 代码)或者报表工具里去做,用 LPAD() 函数或者字符串格式化功能就能轻松实现左边补零。
  3. 3. 没有 ZEROFILL 时: 如果你的字段定义是 INT(3) 或者 INT(11),但没有加 ZEROFILL 属性,那么这个括号里的数字 (M就只是一个非常微弱的提示信息,绝大部分客户端(包括命令行、phpMyAdmin、各种数据库工具)在显示数字时会忽略它。它几乎没有任何实际效果。你存 5,它就显示 5;你存 123456,它就显示 123456

四、终极结论 & 你应该怎么做

  • • INT(3) 和 INT(11) 的核心区别: 仅在启用 ZEROFILL 时,影响查询结果中数字左侧补零的位数INT(3) ZEROFILL 最少补足到3位显示,INT(11) ZEROFILL 最少补足到11位显示。它们不改变存储空间,不改变数值范围!
  • • 现代开发最佳实践:
    1. 1. 避免使用 ZEROFILL 尤其是在 MySQL 8.0 及以上版本。把数字格式化的任务(比如工号补零、日期补零)交给你的应用程序代码或前端展示层。
    2. 2. 简化你的 INT 定义: 如果你不需要 ZEROFILL(或者根本不知道它干嘛用的),那么在定义整数字段时,直接写 INT 就够了! 括号里的数字 (M) 完全可以省略。写成 INT 和写成 INT(11)INT 的默认显示宽度是 11)在功能上没有任何区别,而且 INT 更简洁清晰。
    3. 3. 别再纠结括号里的数字: 看到 INT(10) 也不要慌,它和 INT(1)INT(20) 在存储上依然是一样的!那个数字对存储和范围毫无影响。

总结一句话

MySQL 中 INT 后面括号里的数字 (M),就是个负责 “颜值”(显示时左边补零)的“小助手”,跟 INT 本身的 “实力”(存储空间和数值范围)没有 毛线关系!在绝大多数情况下,放心大胆地直接用 INT 就好啦!💪🏻

希望这篇文章能彻底解开你对 INT(3) 和 INT(11) 的疑惑!下次看到它们,或者看到同事用了 INT(10),你就可以淡定地分享这个知识点了!😉

公众号:BiggerBoy | 作者:北哥

欢迎关注【BiggerBoy】公众号,技术干货持续奉上!

图片