INT型別知多少

kun_行者發表於2019-06-21

前言:
整型是MySQL中最常用的欄位型別之一,通常用於儲存整數,其中int是整型中最常用的,對於int型別你是否真正瞭解呢?本文會帶你熟悉int型別相關知識,也會介紹其他整型欄位的使用。

1.整型分類及儲存範圍

整數型別 位元組 有符號範圍 無符號範圍
TINYINT 1 -128 ~ 127 0 ~ 255
SMALLINT 2 -32768 ~ 32767 0 ~ 65535
MEDIUMINT 3 -8388608 ~ 8388607 0 ~ 16777215
INT/INTEGER 4 -2147483648 ~ 2147483647 0 ~ 4294967295
BIGINT 8 -9223372036854775808 ~ 9223372036854775807 0 ~ 18446744073709551615

表格一共有四列分別表示:欄位型別, 佔用位元組數, 有符號範圍, 無符號範圍。
我們拿int型別為例:
int型別, 佔用位元組數為4byte, 學過計算機原理的同學應該知道, 位元組(byte)並非是計算機儲存的最小單位, 還有比位元組(byte)更小的單位, 也就是位(bit),一個位就代表一個0或1; 8個位組成一個位元組; 一般位元組用大寫B來表示byte, 位用小寫b來表示bit.

計算機儲存單位的換算:
1B=8b
1KB=1024B
1MB=1024KB

那麼根據int型別允許儲存的位元組數是4個位元組, 我們就能換算出int UNSIGNED(無符號)型別的能儲存的最小值為0, 最大值為4294967295(即4B=32b, 最大值即為32個1組成,即4294967295換算成二進位制則是32個1)。

2.儲存範圍測試

mysql> CREATE TABLE test_int (
    -> col1 TINYINT,
    -> col2 SMALLINT,
    -> col3 MEDIUMINT,
    -> col4 INT,
    -> col5 BIGINT
    -> ) ENGINE = INNODB DEFAULT CHARSET = utf8;
Query OK, 0 rows affected (0.01 sec)

mysql> show create table test_int\G
*************************** 1. row ***************************
       Table: test_int
Create Table: CREATE TABLE `test_int` (
  `col1` tinyint(4) DEFAULT NULL,
  `col2` smallint(6) DEFAULT NULL,
  `col3` mediumint(9) DEFAULT NULL,
  `col4` int(11) DEFAULT NULL,
  `col5` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> insert into test_int values (1234,123456,12345678,12345678901,12345678901234567890);
Query OK, 1 row affected, 5 warnings (0.00 sec)

mysql> insert into test_int values (-1234,-123456,-12345678,-12345678901,-12345678901234567890);
Query OK, 1 row affected, 5 warnings (0.01 sec)

mysql> show warnings;
+---------+------+-----------------------------------------------+
| Level   | Code | Message                                       |
+---------+------+-----------------------------------------------+
| Warning | 1264 | Out of range value for column 'col1' at row 1 |
| Warning | 1264 | Out of range value for column 'col2' at row 1 |
| Warning | 1264 | Out of range value for column 'col3' at row 1 |
| Warning | 1264 | Out of range value for column 'col4' at row 1 |
| Warning | 1264 | Out of range value for column 'col5' at row 1 |
+---------+------+-----------------------------------------------+
5 rows in set (0.01 sec)

mysql> select * from test_int;
+------+--------+----------+-------------+----------------------+
| col1 | col2   | col3     | col4        | col5                 |
+------+--------+----------+-------------+----------------------+
|  127 |  32767 |  8388607 |  2147483647 |  9223372036854775807 |
| -128 | -32768 | -8388608 | -2147483648 | -9223372036854775808 |
+------+--------+----------+-------------+----------------------+

從上述測試中我們可以看出:有符號時,各種整型型別最大的儲存範圍,當儲存數字大小不在儲存範圍時,MySQL會產生告警,但數字可以插入,預設擷取為可儲存的最大值或最小值。

3.int(M)中M的含義與zerofill的使用

我們經常聽到這句話:int(M)中的M代表最大顯示寬度,"最大顯示寬度"我們第一反應是該欄位的值最大能允許存放的值的寬度,以為我們建了int(1),就不能存放資料10了, 其實不是這個意思。
整數列的顯示寬度與mysql需要用多少個字元來顯示該列數值,與該整數需要的儲存空間的大小都沒有關係,比如,不管設定了顯示寬度是多少個字元,int都是佔用4個位元組,bigint都要佔用8個位元組。即int(5)和int(10)可儲存的範圍一樣。
整型欄位有個ZEROFILL屬性(0填充),在數字長度不夠的資料前面填充0,以達到設定的長度。加上ZEROFILL後M才表現出不同,當使用ZEROFILL時,預設會自動加unsigned(無符號)屬性。比如 INT(3) ZEROFILL,你插入到資料庫裡的是10,則實際插入為010,也就是在前面補充加了一個0,下面我們來測試下:

mysql> CREATE TABLE test_int_zerofill (
    -> col1 INT(5) ZEROFILL,
    -> col2 INT ZEROFILL,
    -> col3 INT(5)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)

mysql> show create table test_int_zerofill\G
*************************** 1. row ***************************
       Table: test_int_zerofill
Create Table: CREATE TABLE `test_int_zerofill` (
  `col1` int(5) unsigned zerofill DEFAULT NULL,
  `col2` int(10) unsigned zerofill DEFAULT NULL,
  `col3` int(5) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> insert into test_int_zerofill values (12,12,12);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test_int_zerofill;
+-------+------------+------+
| col1  | col2       | col3 |
+-------+------------+------+
| 00012 | 0000000012 |   12 |
+-------+------------+------+
1 row in set (0.00 sec)

那麼有同學可能會問zerofill有什麼應用場景呢,比較常用的應該是月份或日期前補0,這樣顯示的會規範些

CREATE TABLE `t_zerofill` (  
  `year` year(4) DEFAULT NULL,  
  `month` int(2) unsigned zerofill DEFAULT NULL,  
  `day` int(2) unsigned zerofill DEFAULT NULL  
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mysql> insert into t_zerofill values (2019,6,5);
Query OK, 1 row affected (0.01 sec)

mysql> insert into t_zerofill values (2019,6,18);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_zerofill values (2019,10,1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_zerofill values (2019,11,11);
Query OK, 1 row affected (0.01 sec)

mysql> select * from t_zerofill;
+------+-------+------+
| year | month | day  |
+------+-------+------+
| 2019 |    06 |   05 |
| 2019 |    06 |   18 |
| 2019 |    10 |   01 |
| 2019 |    11 |   11 |
+------+-------+------+
4 rows in set (0.00 sec)

4.型別選取

經過上面的介紹,關於不同整型欄位的選取變得容易很多。本著最小化儲存的原則,當然是能選TINYINT不選SMALLINT,能選MEDIUMINT不選INT了,不過一切都要滿足業務的前提下儘量選取佔用位元組更少的型別。對於確定只儲存正整數的欄位,可以加上unsigned屬性,這樣會使儲存範圍更大,比如當欄位有AUTO_INCREMENT屬性時,我們可以為int型別加上unsigned屬性。

相關文章