MySQL的类型:BigInt(20) vs Int(20)

我想知道BigIntMediumIntInt之间的区别是什么…很明显,他们会考虑到更大的数字;然而,我可以创建Int(20)BigInt(20),这样看起来它并不一定与大小有关。

如果能有洞察力就太好了,只是有点好奇。我已经使用MySQL一段时间了,并试图在选择类型时应用业务需求,但我从未理解这方面。

275677 次浏览

类型声明中括号中的数字是显示宽度,它与数据类型中可存储的值范围无关。仅仅因为你可以声明Int(20)并不意味着你可以在其中存储高达10^20的值:

[…应用程序可以使用这个可选的显示宽度来显示宽度小于列指定宽度的整数值,通过左填充空格. ...

显示宽度不限制可以存储在列中的值的范围,也不限制宽度超过列指定宽度的值所显示的位数。例如,指定为SMALLINT(3)的列通常的SMALLINT范围为-32768到32767,并且在三个字符允许的范围之外的值将使用三个以上的字符显示。

对于每个MySQL数据类型中可以存储的最大值和最小值的列表,请参见here

看到http://dev.mysql.com/doc/refman/8.0/en/numeric-types.html

  • INT是一个四字节的有符号整数。

  • BIGINT是一个8字节的有符号整数。

它们各自接受的值不多于也不少于它们各自的字节数所能存储的值。这意味着INT中的232值和BIGINT中的264值。

INT(20)BIGINT(20)中的20几乎没有意义。这是一个显示宽度的提示。它与存储无关,也与列接受的值范围无关。

实际上,它只影响ZEROFILL选项:

CREATE TABLE foo ( bar INT(20) ZEROFILL );
INSERT INTO foo (bar) VALUES (1234);
SELECT bar from foo;


+----------------------+
| bar                  |
+----------------------+
| 00000000000000001234 |
+----------------------+

MySQL用户看到INT(20)并认为它是一个大小限制,这是一个常见的困惑来源,类似于CHAR(20)。事实并非如此。

报价:

“BIGINT(20)”规范不是数字限制。这只是意味着,当数据显示时,如果它使用的数字少于20位,它将用零填充左侧。2^64是BIGINT类型的硬限制,它本身有20位数字,因此BIGINT(20)只是意味着小于10^20的所有内容都将显示为空格。

我想再补充一点,如果你存储的是一个非常大的数字,比如902054990011312,那么你可以很容易地看到INT(20)BIGINT(20)的区别。建议将其存储在BIGINT中。

据我所知,只有一个小的区别是当你试图插入超出范围的值时。

在示例中,我将使用401421228216,它是101110101110110100100011101100010111000(长度39字符)

  • 如果你有INT(20)为系统,这意味着在内存中分配最少20位。但如果你插入的值大于2^20,则只有当它小于INT(32) -> 2147483647(或UNSIGNED2 * INT(32) -> 4294967295)时,它才会被成功存储。

例子:

mysql> describe `test`;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(20) unsigned | YES  |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
1 row in set (0,00 sec)


mysql> INSERT INTO `test` (`id`) VALUES (401421228216);
ERROR 1264 (22003): Out of range value for column 'id' at row 1


mysql> SET sql_mode = '';
Query OK, 0 rows affected, 1 warning (0,00 sec)


mysql> INSERT INTO `test` (`id`) VALUES (401421228216);
Query OK, 1 row affected, 1 warning (0,06 sec)


mysql> SELECT * FROM `test`;
+------------+
| id         |
+------------+
| 4294967295 |
+------------+
1 row in set (0,00 sec)
  • 如果你有BIGINT(20)为系统,这意味着在内存中分配最少20位。但如果你插入的值大于2^20,则它将被成功存储,如果它小于BIGINT(64) -> 9223372036854775807(或UNSIGNED2 * BIGINT(64) -> 18446744073709551615)

例子:

mysql> describe `test`;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| id    | bigint(20) unsigned | YES  |     | NULL    |       |
+-------+---------------------+------+-----+---------+-------+
1 row in set (0,00 sec)


mysql> INSERT INTO `test` (`id`) VALUES (401421228216);
Query OK, 1 row affected (0,04 sec)


mysql> SELECT * FROM `test`;
+--------------+
| id           |
+--------------+
| 401421228216 |
+--------------+
1 row in set (0,00 sec)

让我们举一个int(10)的例子,一个有zerofill关键字,一个没有,表格是这样的:

create table tb_test_int_type(
int_10 int(10),
int_10_with_zf int(10) zerofill,
unit int unsigned
);

让我们插入一些数据:

insert into tb_test_int_type(int_10, int_10_with_zf, unit)
values (123456, 123456,3147483647), (123456, 4294967291,3147483647)
;

然后

select * from tb_test_int_type;


# int_10, int_10_with_zf, unit
'123456', '0000123456', '3147483647'
'123456', '4294967291', '3147483647'

我们可以看到

  • 使用关键字zerofill, num小于10将填充0,但没有zerofill则不会

  • 其次,对于关键字zerofill, int_10_with_zf变成无符号int类型,如果插入减号,将得到错误Out of range value for column.....。但是你可以在int_10中插入减号。另外,如果你插入4294967291到int_10,你会得到错误Out of range value for column.....

结论:

  1. 没有zerofill关键字的int(X),等于int范围-2147483648~2147483647

  2. int(X),关键字zerofill,该字段等于无符号int范围0~4294967295,如果num的长度小于X,它将在左边填充0