SQL语句中的 int 和 int(n)有什么区别?为什么没有varchar, 通常都是 varchar(n)?

67 阅读8分钟
  • 先回答问题,intint(n) 在大多数场景下没有区别,直接使用 int即可
  • varchar(n) 里的 n 是用来指定最大存储长度的,所以需要写
  • 总结来说:int 类型的存储长度在设计之初已经规定好了,而 varchar 类型的存储长度 由用户自行决定。就像你去购物,想要一个袋子可以装5斤苹果,但超市的袋子(int类型)只能装3斤多了也装不了,但你可以自己做一个袋子(varchar)规定好最大有多大,这个袋子很神奇像气球一样,虽然也有上限,但当你装1斤苹果的时候它会自己缩小,而超过上限也装不了了。

下面你可以退出,也可以看一下这两个为什么的详细解答。

对于 int 类型的字段(比如自增长的 id),写 int(30) 和不写(直接写 int)的区别,仅体现在 “是否显式指定了显示宽度” 这一点上,而对字段的核心能力(存储范围、自增长逻辑、查询性能)完全没有影响。具体可以从两个场景拆解:

场景 1:没有使用 ZEROFILL 属性(99% 的业务场景)

这是最常见的情况(比如用户表的 id 通常不需要 “零填充显示”),此时 写与不写没有任何可感知的区别

  • 存储层面:无论 int 还是 int(30),都占用 4 字节,取值范围都是 -2147483648~2147483647(有符号)或 0~4294967295(无符号);

  • 自增长层面:两者的自增长逻辑完全一致,上限都是 int 本身的最大值(不会因 (30) 变高);

  • 查询显示层面:查询结果都按 “实际数值长度” 显示(比如 id=123,两种写法都显示为 123,不会多补 0);

  • 语法合法性:两种写法都符合 MySQL 语法,不会报错。

总结:这种场景下,int(30) 的 (30) 就是 “冗余配置”,写了和没写一样,没有实际作用。

场景 2:使用了 ZEROFILL 属性(极少用,仅用于格式化显示)

ZEROFILL 是 MySQL 的一个特殊属性,作用是 “当数值长度小于显示宽度时,用 0 在前面补齐”。只有在这种情况下,int(30) 和 int(默认显示宽度)才会有区别 —— 但区别仅体现在 “补 0 的位数” 上,仍不影响存储和自增长。

先明确:int 不写显示宽度时,MySQL 会用默认显示宽度

  • 有符号 int:默认显示宽度是 11(因为有符号最大是 -2147483648,共 11 个字符,含负号);

  • 无符号 int:默认显示宽度是 10(无符号最大是 4294967295,共 10 个字符)。

举个具体例子(假设 id 是无符号自增长,当前值为 123):

字段定义是否用 ZEROFILL实际存储值查询显示结果核心区别(仅显示)
int(默认 int(10)1230000000123(补 8 个 0)按默认宽度 10 位补 0
int(30)123000000000000000000000000000123(补 27 个 0)按显式宽度 30 位补 0
int 或 int(30)123123无区别,都正常显示

总结:只有开启 ZEROFILL 时,int(30) 和 int 才会有 “显示效果” 的区别,但这种场景极少(比如仅用于需要固定位数格式的编号,如发票号、订单号,但这类需求更常用 varchar 配合函数实现,而非 int+ZEROFILL)。

最终结论:写与不写的核心区别

对比维度写 int(30)不写(直接 int
存储范围无区别(均为 int 本身的范围)无区别
自增长逻辑无区别无区别
查询性能无区别无区别
显示效果(无 ZEROFILL无区别(均按实际数值显示)无区别
显示效果(有 ZEROFILL按 30 位补 0按默认宽度(10/11 位)补 0
语法冗余度有冗余((30) 无实际意义)更简洁(推荐)

简单说:99% 的业务场景下,写 int(30) 和直接写 int 没有任何区别(30) 只是一个 “不影响功能的冗余配置”;只有极特殊的 ZEROFILL 场景下,才会有显示效果的差异,但这种场景几乎用不到。

下面我们来看看为什么 varchar类型 要使用 varchar(n) 的形式表述?


要理解这个问题,核心在于两种数据类型的 “存储机制” 和 “括号内数字的含义” 完全不同int 是 “固定长度整数类型”,括号内数字是 “显示宽度”(非必需);varchar 是 “可变长度字符串类型”,括号内数字是 “最大存储长度”(必需)。下面分维度详细解释:

一、先明确:两种类型括号内数字的 “本质含义” 天差地别

很多人误以为 int (20) 和 varchar (12) 的括号都是 “存储长度”,但实际上两者的作用完全不同,这是问题的根源。

数据类型括号内数字的含义是否必需对 “存储大小” 的影响
int显示宽度(仅控制查询结果的显示格式)无影响,int 的存储大小固定为 4 字节
varchar最大存储长度(限制字段能存的字符数)直接决定字段最多能存多少字符,存储大小随实际内容变化

二、为什么 int 可以不写括号(如直接用 int)?

int固定长度的整数类型,其核心特性是 “存储大小不随数值变化”,括号内的数字(如 int (20))仅作用于 “显示层面”,不影响存储和计算。

1. int 的 “存储大小是固定的”,与括号无关

以主流数据库(如 MySQL、SQL Server)为例:

  • int 类型 的存储大小固定为 4 字节,无论你存的是 1、100、还是 2147483647(int 的最大值),都会占用 4 字节。
  • 括号内的数字(如 int (5)、int (20))不是 “存储长度”,而是显示宽度—— 仅当查询结果需要 “补零显示” 时才有用(需配合zerofill属性)。

2. 显示宽度的实际作用(非必需)

显示宽度的意义非常有限,仅用于 “格式化显示数值”,不影响数据本身。例如:

  • 定义字段为 int(5) zerofill(zerofill 是 “补零” 属性):

    • 存入数值 123,查询时会显示 00123(补够 5 位);
    • 存入数值 123456,查询时会显示 123456(超过显示宽度时,按实际数值显示)。
  • 如果不写括号(直接用 int),数据库会使用默认显示宽度(如 MySQL 中 int 默认是 int (11)),但这完全不影响存储和计算 —— 你存的数值大小、占用空间都不变。

三、为什么 varchar 必须写括号(如 varchar (12))?

varchar可变长度的字符串类型,其核心特性是 “存储大小随实际内容变化”,但必须有一个 “最大长度限制”—— 括号内的数字就是这个限制,是数据库创建字段的 “必需参数”。

1. varchar 的 “存储大小依赖最大长度”

varchar 的存储逻辑是:

  • 实际存储时,占用的空间 = 字符本身的字节数 + 1~2 字节的 “长度标识”(记录实际字符的长度);
  • 最多能存多少字符,必须由括号内的数字定义(如 varchar (12) 表示最多存 12 个字符)。

例如:

  • 定义 varchar(12),存入 “abc”(3 个字符),实际占用空间约 3 + 1 = 4 字节;
  • 若试图存入 “abcdefghijklm”(13 个字符),数据库会直接报错(超过最大长度限制)。

2. 为什么必须指定最大长度?

数据库需要这个 “最大长度” 来做三件关键事:

  1. 分配存储空间上限:虽然 varchar 是可变长度,但数据库需要知道 “最坏情况下” 这个字段可能占用多少空间,以便优化磁盘布局和内存缓存;
  2. 数据校验:防止插入超过预期长度的无效数据(比如 “用户手机号” 字段,定义 varchar (11) 就能避免存入 12 位的错误号码);
  3. 索引优化:字符串索引的建立依赖字段的最大长度,过长的字符串会导致索引效率下降,指定合理的最大长度能提升查询性能。

3. 结论:varchar 的括号是 “必需的”

如果不指定最大长度(如只写varchar),数据库无法确定这个字段的存储上限、无法做数据校验,因此会直接报错(主流数据库如 MySQL 5.7+、SQL Server 都不允许这种写法)。

四、一句话总结核心差异

  • int:固定 4 字节存储,括号内是 “显示宽度”(非必需,不影响数据)→ 所以可以直接写 int;
  • varchar:可变长度存储,括号内是 “最大字符数”(必需,决定存储上限)→ 所以必须写 varchar (n)。

这本质上是 “整数类型的固定存储特性” 与 “字符串类型的可变存储特性” 决定的设计差异。