ประเภทใน MySQL: BigInt (20) vs Int (20)


221

ฉันสงสัยว่าความแตกต่างระหว่างBigInt, MediumIntและIntคือ ... ดูเหมือนว่าพวกเขาจะยอมให้มีจำนวนมากขึ้น อย่างไรก็ตามฉันสามารถสร้างInt(20)หรือ a BigInt(20)และที่จะทำให้ดูเหมือนว่ามันไม่จำเป็นต้องเกี่ยวกับขนาด

ความเข้าใจบางอย่างจะยอดเยี่ยมเพียงแค่อยากรู้อยากเห็น ฉันใช้MySQLมาระยะหนึ่งแล้วพยายามใช้ความต้องการทางธุรกิจเมื่อเลือกประเภท แต่ฉันไม่เคยเข้าใจเรื่องนี้เลย

คำตอบ:


479

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

  • INT เป็นจำนวนเต็มแบบสี่ไบต์

  • BIGINT เป็นจำนวนเต็มแบบแปดไบต์

พวกเขาแต่ละคนยอมรับไม่มากและไม่น้อยกว่าค่าที่สามารถเก็บไว้ในจำนวนไบต์ที่เกี่ยวข้อง นั่นหมายความว่า 2 32ค่าในINT2 64BIGINTค่าใน

20 นิ้วINT(20)และBIGINT(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)ของขนาดบางสิ่งบางอย่างที่คล้ายคลึงกับ กรณีนี้ไม่ได้.


4
ว้าวโพสต์นี้กำจัดความสับสนของฉันในเรื่องนี้อย่างสมบูรณ์แบบ ดูเหมือนจะเป็นทางเลือกที่แปลกโดยนักพัฒนา - เพราะฉันเดาได้ว่ามันคือความกว้าง + ค่าสูงสุดหรือบิต / ฯลฯ
Sh4d0wsPlyr

27
`มันมีผลกับตัวเลือก ZEROFILL เท่านั้น: 'ตอนนี้ความอยากรู้ของฉันจบลง
Umair

6
ฉันหวังว่าพวกเขาจะออกแบบไวยากรณ์ด้วยจอแสดงผลบน ZEROFILL แทนที่จะเป็น INT ตัวอย่าง: bar INT ZEROFILL(20). มันจะชัดเจนมากขึ้น แต่การตัดสินใจนั้นทำมานานแล้วและการเปลี่ยนแปลงในตอนนี้จะทำให้การติดตั้งฐานข้อมูลหลายล้านรายการเสียหาย
Bill Karwin

1
ฉันเห็นด้วยว่ามันสับสนมาก ฉันอยู่ภายใต้การแสดงผลที่จำนวนถูก จำกัด ตลอดเวลานี้ แม้แต่ความกังวลเกี่ยวกับการทำให้ตัวเลขเล็กลงเมื่อฉันรู้ว่าข้อมูลจะอยู่ในช่วงที่กำหนด
jDub9

2
@ jDub9 ใช่และมันก็ยิ่งทำให้เกิดความสับสนว่าตัวเลข / ทศนิยมใช้อาร์กิวเมนต์ที่แม่นยำที่ไม่ส่งผลกระทบต่อช่วงของค่าและขนาดของคอลัมน์
Bill Karwin

40

จำนวนในวงเล็บในการประกาศประเภทคือความกว้างของจอแสดงผลซึ่งไม่เกี่ยวข้องกับช่วงของค่าที่สามารถเก็บไว้ในชนิดข้อมูล เพียงเพราะคุณสามารถประกาศInt(20)ไม่ได้หมายความว่าคุณสามารถเก็บค่าได้ถึง 10 ^ 20:

[... ] ความกว้างของจอแสดงผลทางเลือกนี้อาจถูกใช้โดยแอปพลิเคชันเพื่อแสดงค่าจำนวนเต็มที่มีความกว้างน้อยกว่าความกว้างที่ระบุสำหรับคอลัมน์โดยการเว้นระยะห่างด้านซ้ายด้วยช่องว่าง ...

ความกว้างของจอแสดงผลไม่ได้ จำกัด ช่วงของค่าที่สามารถเก็บไว้ในคอลัมน์หรือจำนวนหลักที่แสดงสำหรับค่าที่มีความกว้างเกินกว่าที่ระบุไว้สำหรับคอลัมน์ ตัวอย่างเช่นคอลัมน์ที่ระบุว่าเป็น SMALLINT (3) มีช่วง SMALLINT ปกติเป็น -32768 ถึง 32767 และค่าที่อยู่นอกช่วงที่อนุญาตโดยอักขระสามตัวจะแสดงโดยใช้อักขระมากกว่าสามตัว

สำหรับรายชื่อของค่าสูงสุดและต่ำสุดที่สามารถเก็บไว้ในแต่ละประเภทข้อมูล MySQL ให้ดูที่นี่


18

ข้อความอ้างอิง :

ข้อกำหนด "BIGINT (20)" ไม่ใช่ขีด จำกัด หลัก มันก็หมายความว่าเมื่อมีการแสดงข้อมูลถ้ามันใช้น้อยกว่า 20 หลักมันจะถูกเติมด้วยศูนย์ 2 ^ 64 เป็นขีด จำกัด ที่ยากสำหรับประเภท BIGINT และมีตัวเลข 20 หลักดังนั้น BIGINT (20) จึงหมายถึงทุกอย่างที่น้อยกว่า 10 ^ 20 จะถูกทิ้งไว้ที่ด้านซ้ายด้วยช่องว่างบนจอแสดงผล


3
2 ^ 64 (ไม่ได้ลงชื่อ) จริง ๆ แล้วมี 21 หลัก BIGINT (20) อันตราย คนที่ใช้ดูเหมือนว่าจะปรับการใช้งานของพวกเขาในความคิดที่ว่า 2 ^ 64 เหมาะกับตัวเลขทศนิยม 20 หลัก หากเป็นเช่นนั้นเหตุใดจึงต้องระบุความกว้าง จำกัด เลย เมื่อมันปรากฏออกมานั่นก็ไม่ถูกต้องเช่นกัน ต้องใช้ 21 หลักเพื่อแสดง 2 ^ 64 อย่างถูกต้อง
Heath Hunnicutt

@HeathHunnicutt ยกเว้นว่าฉันเข้าใจผิด 2 ^ 64 = 18446744073709551616 ซึ่งมี 20 หลัก อะไรทำให้คุณพูดว่ามี 21
drmercer

3

เท่าที่ฉันรู้มีความแตกต่างเพียงเล็กน้อยเท่านั้นคือเมื่อคุณพยายามแทรกค่าที่อยู่นอกช่วง

ในตัวอย่างที่ฉันจะใช้401421228216ซึ่งก็คือ101110101110110100100011101100010111000(ความยาว39ตัวอักษร)

  • หากคุณมีINT(20)ระบบนี่หมายความว่าจัดสรรในหน่วยความจำขั้นต่ำ 20 บิต แต่ถ้าคุณจะใส่ค่าที่มากกว่า2^20นั้นมันจะถูกเก็บไว้สำเร็จถ้ามันน้อยกว่านั้นINT(32) -> 2147483647(หรือ2 * INT(32) -> 4294967295สำหรับUNSIGNED)

ตัวอย่าง:

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) -> 18446744073709551615สำหรับUNSIGNED)

ตัวอย่าง:

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)

1

ผมอยากจะเพิ่มอีกจุดหนึ่งคือถ้าคุณเก็บเป็นจำนวนมากชอบ 902054990011312 แล้วหนึ่งสามารถเห็นความแตกต่างของและINT(20) จะแนะนำให้เก็บไว้ในBIGINT(20)BIGINT


1

ลองยกตัวอย่างสำหรับ 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จำนวนที่น้อยกว่า 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. int (X) โดยไม่มีคำหลักzerofillเท่ากับช่วง int -2147483648 ~ 2147483647

  2. int (X) พร้อมคีย์เวิร์ดzerofillฟิลด์เท่ากับช่วง int ที่ไม่ได้ลงชื่อ 0 ~ 4294967295 ถ้าความยาวของ NUM น้อยกว่า X จะเติม 0 ทางซ้าย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.