Typy w MySQL: BigInt (20) vs Int (20)

221

Zastanawiałem się, jaka jest różnica między BigInt, MediumInti Intsą ... wydaje się oczywiste, że pozwalają one na większych liczbach; jednak mogę zrobić a Int(20)lub a, BigInt(20)a to wydawałoby się, że niekoniecznie chodzi o rozmiar.

Pewna wiedza byłaby niesamowita, po prostu ciekawa. Używam MySQL od jakiegoś czasu i staram się stosować potrzeby biznesowe przy wyborze typów, ale nigdy nie zrozumiałem tego aspektu.

Parris
źródło

Odpowiedzi:

478

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

  • INT jest czterobajtową liczbą całkowitą ze znakiem.

  • BIGINT jest ośmiobajtową liczbą całkowitą ze znakiem.

Każdy z nich akceptuje nie więcej i nie mniej wartości, niż można zapisać w odpowiedniej liczbie bajtów. Oznacza to 2 32 wartości w an INTi 2 64 wartości w a BIGINT.

20 w INT(20)i BIGINT(20)oznacza prawie nic. Jest to wskazówka dotycząca szerokości wyświetlacza. Nie ma to nic wspólnego z pamięcią ani zakresem wartości, które zaakceptuje kolumna.

Praktycznie wpływa to tylko na ZEROFILLopcję:

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

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

Jest to powszechne źródło zamieszania dla użytkowników MySQL, którzy widzą INT(20)i zakładają, że jest to limit wielkości, coś analogicznego do CHAR(20). Nie o to chodzi.

Bill Karwin
źródło
4
Wow, ten post doskonale rozwiał moje zamieszanie na ten temat. Wydaje się to dziwnym wyborem ze strony programistów - tak jak bym zgadł, była to szerokość + wartość maksymalna lub bit / etc.
Sh4d0wsPlyr
27
`wpływa tylko na opcję ZEROFILL:` teraz moja ciekawość się kończy
Umair,
6
Naprawdę chciałbym, aby zaprojektowali składnię z wyświetlaczem na ZEROFILL zamiast INT. Przykład: bar INT ZEROFILL(20). Byłoby to o wiele bardziej jasne. Ale ta decyzja została podjęta dawno temu, a zmiana jej teraz złamałaby miliony instalacji baz danych.
Bill Karwin
1
Zgadzam się, że to bardzo mylące. Przez cały czas miałem wrażenie, że liczba jest limitem. Nawet martwiłem się o zmniejszenie niektórych liczb, gdy wiedziałem, że dane będą w określonym zakresie.
jDub9
2
@ jDub9, tak, i jeszcze bardziej mylące jest to, że NUMERIC / DECIMAL przyjmuje precyzyjny argument, który wpływa na zakres wartości i rozmiar kolumny.
Bill Karwin,
40

Liczba w nawiasach w deklaracji typu to szerokość wyświetlania , która nie jest związana z zakresem wartości, które mogą być przechowywane w typie danych. To, że możesz zadeklarować Int(20), nie oznacza, że ​​możesz przechowywać w nim wartości do 10 ^ 20:

[...] Ta opcjonalna szerokość wyświetlania może być używana przez aplikacje do wyświetlania wartości całkowitych o szerokości mniejszej niż szerokość określona dla kolumny, wypełniając je spacjami. ...

Szerokość wyświetlania nie ogranicza zakresu wartości, które mogą być przechowywane w kolumnie, ani liczby cyfr wyświetlanych dla wartości o szerokości przekraczającej tę określoną dla kolumny. Na przykład kolumna określona jako SMALLINT (3) ma zwykle zakres SMALLINT od -32768 do 32767, a wartości spoza zakresu dozwolonego przez trzy znaki są wyświetlane przy użyciu więcej niż trzech znaków.

Aby uzyskać listę maksymalnych i minimalnych wartości, które mogą być przechowywane w każdym typie danych MySQL, zobacz tutaj .

John Feminella
źródło
18

Cytat :

Specyfikacja „BIGINT (20)” nie jest limitem cyfr. Oznacza to po prostu, że gdy dane są wyświetlane, jeśli używa mniej niż 20 cyfr, zostaną one uzupełnione zerami. 2 ^ 64 jest twardym ograniczeniem dla typu BIGINT i ma 20 cyfr, dlatego też BIGINT (20) oznacza po prostu, że wszystko poniżej 10 ^ 20 będzie wypełnione lewą spacją na wyświetlaczu.

Kucyki OMG
źródło
3
2 ^ 64 (niepodpisany) faktycznie ma 21 cyfr. BIGINT (20) jest niebezpieczny. Wydaje się, że ludzie, którzy go używają, uzasadniają to, że 2 ^ 64 mieści się w 20 cyfrach dziesiętnych. Jeśli tak, to po co w ogóle określać limit szerokości? Jak się okazuje, to też nie jest poprawne. 21 cyfr jest potrzebnych do poprawnego wyświetlenia 2 ^ 64.
Heath Hunnicutt
@HeathHunnicutt O ile się nie mylę, 2 ^ 64 = 18446744073709551616, który ma 20 cyfr. Co sprawia, że ​​mówisz, że ma 21?
drmercer
3

O ile mi wiadomo, jest tylko jedna niewielka różnica, gdy próbujesz wstawić wartość spoza zakresu.

W przykładach użyję 401421228216, czyli 101110101110110100100011101100010111000(długość 39 znaków)

  • Jeśli masz INT(20)dla systemu, oznacza to przydzielenie w pamięci minimum 20 bitów. Ale jeśli wstawisz wartość większą niż 2^20, zostanie ona pomyślnie zapisana, tylko jeśli będzie mniejsza niż INT(32) -> 2147483647(lub 2 * INT(32) -> 4294967295dla UNSIGNED)

Przykład:

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)
  • Jeśli masz BIGINT(20)dla systemu, oznacza to przydzielenie w pamięci minimum 20 bitów. Ale jeśli wstawisz wartość większą niż 2^20, zostanie ona pomyślnie zapisana, jeśli jest mniejsza niż BIGINT(64) -> 9223372036854775807(lub 2 * BIGINT(64) -> 18446744073709551615dla UNSIGNED)

Przykład:

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)
Siergiej Podgornyj
źródło
1

Chciałem dodać jeszcze jedną kwestię: jeśli przechowujesz naprawdę dużą liczbę, taką jak 902054990011312, łatwo zauważyć różnicę INT(20)i BIGINT(20). Wskazane jest przechowywanie w BIGINT.

Debasis Sabat
źródło
1

Podajmy przykład dla int (10) jeden ze słowem kluczowym zerofill, jeden nie, tabela lubi to:

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

Wstawmy trochę danych:

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

Następnie

select * from tb_test_int_type; 

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

Widzimy to

  • ze słowem kluczowym liczba zerofillmniejsza niż 10 wypełni 0, ale bez zerofillniej nie

  • Po drugie, ze słowem kluczowym zerofillint_10_with_zf staje się typu int bez znaku, jeśli wstawisz minus, otrzymasz błąd Out of range value for column...... Ale możesz wstawić minus do int_10. Również jeśli wstawisz 4294967291 do int_10, pojawi się błądOut of range value for column.....

Wniosek:

  1. int (X) bez słowa kluczowego zerofill, jest równy int zakres -2147483648 ~ 2147483647

  2. int (X) ze słowem kluczowym zerofill, pole jest równe bez znaku int zakres 0 ~ 4294967295, jeśli długość num jest mniejsza niż X, wypełni 0 po lewej

Jayhello
źródło