Tipos no MySQL: BigInt (20) vs Int (20)

221

Fiquei me perguntando qual a diferença entre BigInt, MediumInte Intsão ... parece óbvio que eles permitiriam números maiores; no entanto, posso fazer um Int(20)ou um BigInt(20)e isso faria parecer que não é necessariamente sobre tamanho.

Alguma visão seria incrível, meio que curiosa. Estou usando o MySQL há um tempo e tentando aplicar as necessidades de negócios ao escolher tipos, mas nunca entendi esse aspecto.

Parris
fonte

Respostas:

478

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

  • INT é um número inteiro assinado de quatro bytes.

  • BIGINT é um número inteiro assinado de oito bytes.

Cada um deles aceita nem mais nem menos valores do que os que podem ser armazenados em seu respectivo número de bytes. Isso significa 2 32 valores em um INTe 2 64 valores em a BIGINT.

Os 20 polegadas INT(20)e BIGINT(20)significa quase nada. É uma dica para a largura da tela. Não tem nada a ver com armazenamento, nem o intervalo de valores que essa coluna aceitará.

Praticamente, afeta apenas a ZEROFILLopção:

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

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

É uma fonte comum de confusão para os usuários do MySQL verem INT(20)e assumirem que é um limite de tamanho, algo análogo ao CHAR(20). Este não é o caso.

Bill Karwin
fonte
4
Uau, este post esclareceu minha confusão sobre esse assunto perfeitamente. Parece uma escolha estranha pelos desenvolvedores - como eu teria imaginado que era largura + valor máximo, ou bits / etc.
Sh4d0wsPlyr
27
`afeta apenas a opção ZEROFILL:` agora minha curiosidade termina
Umair
6
Eu realmente gostaria que eles tivessem projetado a sintaxe com a tela com ZEROFILL em vez de INT. Exemplo: bar INT ZEROFILL(20). Teria sido muito mais claro. Mas essa decisão foi tomada há muito tempo e alterá-la agora quebraria milhões de instalações de banco de dados.
Bill Karwin
1
Eu concordo que isso é muito confuso. Fiquei com a impressão de que esse número era o limite todo esse tempo. Mesmo preocupado em diminuir alguns números quando soube que os dados estariam dentro de um determinado intervalo.
JDub9:
2
@ jDub9, sim, e é ainda mais confuso que NUMERIC / DECIMAL tomar um argumento precisão que faz afetam o intervalo de valores e o tamanho da coluna.
Bill Karwin
40

O número entre parênteses em uma declaração de tipo é a largura de exibição , que não está relacionada ao intervalo de valores que podem ser armazenados em um tipo de dados. Só porque você pode declarar Int(20)não significa que você pode armazenar valores de até 10 ^ 20 nele:

[...] Essa largura de exibição opcional pode ser usada por aplicativos para exibir valores inteiros com largura inferior à largura especificada para a coluna, preenchendo-os com espaços à esquerda. ...

A largura da exibição não restringe o intervalo de valores que podem ser armazenados na coluna, nem o número de dígitos que são exibidos para valores com largura superior à especificada para a coluna. Por exemplo, uma coluna especificada como SMALLINT (3) tem o intervalo SMALLINT usual de -32768 a 32767 e os valores fora do intervalo permitido por três caracteres são exibidos usando mais de três caracteres.

Para uma lista dos valores máximos e mínimos que podem ser armazenados em cada tipo de dados MySQL, veja aqui .

John Feminella
fonte
18

Citação :

A especificação "BIGINT (20)" não é um limite de dígitos. Significa apenas que, quando os dados são exibidos, se usarem menos de 20 dígitos, serão preenchidos à esquerda com zeros. 2 ^ 64 é o limite rígido para o tipo BIGINT e possui 20 dígitos, portanto, BIGINT (20) significa apenas que menos de 10 ^ 20 será preenchido à esquerda com espaços em exibição.

Pôneis OMG
fonte
3
2 ^ 64 (sem sinal) na verdade tem 21 dígitos. BIGINT (20) é perigoso. As pessoas que o usam parecem justificar seu uso com a idéia de que 2 ^ 64 cabe em 20 dígitos decimais. Se for esse o caso, por que especificar um limite de largura? Como se vê, isso também não está correto. São necessários 21 dígitos para exibir corretamente 2 ^ 64.
Heath Hunnicutt
@HeathHunnicutt A menos que eu esteja enganado, 2 ^ 64 = 18446744073709551616, que possui 20 dígitos. O que faz você dizer que tem 21?
drmercer 13/01
3

Até onde eu sei, há apenas uma pequena diferença quando você está tentando inserir um valor que está fora do intervalo.

Nos exemplos que vou usar 401421228216, que é 101110101110110100100011101100010111000(tamanho 39 caracteres)

  • Se você possui INT(20)um sistema, isso significa alocar na memória no mínimo 20 bits. Mas se você inserir um valor maior que 2^20, ele será armazenado com êxito, apenas se for menor que INT(32) -> 2147483647(ou 2 * INT(32) -> 4294967295para UNSIGNED)

Exemplo:

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)
  • Se você possui BIGINT(20)um sistema, isso significa alocar na memória no mínimo 20 bits. Mas se você inserir um valor maior que 2^20, ele será armazenado com sucesso, se for menor que BIGINT(64) -> 9223372036854775807(ou 2 * BIGINT(64) -> 18446744073709551615para UNSIGNED)

Exemplo:

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)
Sergey Podgornyy
fonte
1

Queria acrescentar mais um ponto: se você estiver armazenando um número realmente grande como 902054990011312, poderá ver facilmente a diferença de INT(20)e BIGINT(20). É aconselhável armazenar em BIGINT.

Debasis Sabat
fonte
1

Vamos dar um exemplo para int (10) um com a palavra-chave zerofill, outro não, a tabela gosta disso:

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

Vamos inserir alguns dados:

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

Então

select * from tb_test_int_type; 

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

Nós podemos ver isso

  • com a palavra-chave zerofill, num inferior a 10 preencherá 0, mas sem zerofillela não

  • Em segundo lugar, com a palavra-chave zerofill, int_10_with_zf se torna um tipo int sem sinal; se você inserir um sinal de menos, receberá um erro Out of range value for column...... Mas você pode inserir menos para int_10. Além disso, se você inserir 4294967291 em int_10, receberá um erroOut of range value for column.....

Conclusão:

  1. int (X) sem palavra-chave zerofill, é igual ao intervalo int -2147483648 ~ 2147483647

  2. int (X) com a palavra-chave zerofill, o campo é igual ao intervalo int não assinado de 0 a 4294967295, se o comprimento de num for menor que X, ele preencherá 0 à esquerda

Jayhello
fonte