MySQL 中的类型:BigInt(20) 与 Int(20)

Posted

技术标签:

【中文标题】MySQL 中的类型:BigInt(20) 与 Int(20)【英文标题】:Types in MySQL: BigInt(20) vs Int(20) 【发布时间】:2011-03-09 07:50:08 【问题描述】:

我想知道BigIntMediumIntInt 之间的区别是什么……显然它们允许更大的数字;但是,我可以制作一个 Int(20)BigInt(20),这看起来并不一定与大小有关。

一些洞察力会很棒,只是有点好奇。我用MySQL有一段时间了,在选择类型的时候尝试应用业务需求,但是一直没搞懂这方面。

【问题讨论】:

【参考方案1】:

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

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

BIGINT 是一个八字节有符号整数。

它们每个接受的值都不能超过它们各自的字节数。这意味着 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),这是一个常见的混淆来源。事实并非如此。

【讨论】:

哇,这篇文章完美地解决了我对这个问题的困惑。开发人员似乎是一个奇怪的选择 - 正如我猜想的那样,它是宽度 + 最大值,或位/等。 ` 它只影响 ZEROFILL 选项:` 现在我的好奇心结束了 我真的希望他们设计的语法显示为 ZEROFILL 而不是 INT。示例:bar INT ZEROFILL(20)。它会更清楚。但这个决定是很久以前做出的,现在改变它会破坏数百万个数据库安装。 我同意这很令人困惑。我的印象是数字一直是限制。当我知道数据会在一定范围内时,甚至担心会缩小一些数字。 @jDub9,是的,更令人困惑的是 NUMERIC/DECIMAL 采用 确实 影响值范围和列大小的精度参数。【参考方案2】:

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

[...] 应用程序可以使用这个可选的显示宽度来显示宽度小于为列指定的宽度的整数值,方法是用空格向左填充它们。 ...

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

有关可以存储在每个 MySQL 数据类型中的最大值和最小值的列表,请参阅 here

【讨论】:

【参考方案3】:

Quote:

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

【讨论】:

2^64(无符号)实际上有 21 位数字。 BIGINT(20) 很危险。使用它的人似乎证明他们使用 2^64 适合 20 个十进制数字的想法是合理的。如果是这样,为什么要指定宽度限制呢?事实证明,这也不正确。正确显示 2^64 需要 21 位数字。 @HeathHunnicutt 除非我弄错了,否则 2^64 = 18446744073709551616,它有 20 位数字。是什么让你说它有 21 个?【参考方案4】:

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

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

如果系统有INT(20),这意味着在内存中分配至少20 位。但是,如果您插入的值大于2^20,它将成功存储,前提是它小于INT(32) -> 2147483647(或2 * INT(32) -> 4294967295UNSIGNED

示例:

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(或2 * BIGINT(64) -> 18446744073709551615UNSIGNED

示例:

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)

【讨论】:

【参考方案5】:

我们举个例子 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 变为 unsigned int 类型,如果插入减号,则会出现错误Out of range value for column.....。但是您可以在 int_10 中插入减号。此外,如果您将 4294967291 插入 int_10,您将收到错误 Out of range value for column.....

结论:

    int(X)不带关键字zerofill,等于int范围-2147483648~2147483647

    int(X) 带关键字zerofill,字段等于unsigned int 范围0~4294967295,如果num的长度小于X则向左补0

【讨论】:

【参考方案6】:

我想再补充一点,如果你要存储一个非常大的数字,比如 902054990011312,那么很容易看出INT(20)BIGINT(20) 的区别。建议存储在BIGINT

【讨论】:

以上是关于MySQL 中的类型:BigInt(20) 与 Int(20)的主要内容,如果未能解决你的问题,请参考以下文章

mysql解释类型索引与所有性能问题

mysql bigint(20) 20指的是啥意思

MySQL:bigint 与 int

SQL-将BIGINT(20)转换为日期时间数据类型

MYSQL中的数值型数据类型与字符串类型

mysql数据类型/注意事项/int(20)混淆