1. 前言
MySQL 中支持的數據類型從整體上可以分為數值類型和日期時間類型,其中數值類型可以分為整數類型、浮點數類型、定點數類型和位類型。整數類型包含常見的 SMALLINT、MEDIUMINT、INT、BIGINT,浮點數類型主要是 FLOAT 單精度浮點數類型和 DOUBLE 雙精度浮點數類型。日期類型也有 DATE、TIME、YEAR、DATETIME、TIMESTAMP 類型。關于整數類型和浮點數類型存在一些比較常見的誤區,經常被面試官考察。
2. int (3) 和 int (11)
面試官提問: MySQL 中 int (3) 和 int (11) 這兩種用法有什么區別呢?
題目解析:
這道題非常常見,但是沒有仔細了解過 MySQL 中 int
數據類型用法的同學,很容易掉進誤區。
我們知道 varchar(m)
用于修飾變長字符,其中 m 表示能夠存儲的字符上限。
例如 username varchar(2)
在 MySQL 5.0 之后的版本表示最多接受 2 個漢字的字符作為用戶名存儲,如果長度超限會報錯:ERROR 1406 (22001): Data too long for column 'username' at row 1
。所以候選人可能會想當然的認為 int(m)
中的 m 表示存儲數字的長度,int(3)
和 int(11)
分別表示最多存儲 3 位數和 11 位數,這種觀點是完全錯誤的!
2.1 int (3) 和 int (11) 占用的硬件存儲空間完全相同
首先,我們在申明某個字段數據類型為 int
的時候,不管是 int(3)
還是 int(11)
,在 MySQL 中存儲時都占用 4 個字節的長度。
1 個字節(Byte) = 8 個二進制位(bit),所以 1 個 int = 4 Byte = 4 * 8 bit = 32 bit,計算機中使用首個比特位存儲數字符號(參考補碼的定義),所以可以算出 int(m)
的存儲范圍在 [-2147483648,2147483647]
之間。
2.2 int (3) 和 int (11) 在 zerofill 關鍵詞修飾時展示不同
我們在之前創建的 mooc_demo
數據庫中創建一張測試表:
DROP TABLE IF EXISTS `test_int`;
CREATE TABLE `test_int` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '數據庫主鍵',
`num1` int(3) zerofill,
`num2` int(11) zerofill
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
再插入一條測試數據:
insert into test_int (num1, num2) values (1,1);
現在執行 select * from test_int;
查詢語句,查詢結果如圖:
如上圖所示,存儲相同的數字 1,num1 前補全了 2 個 0,num2 前補全了 10 個 0,
所以可以得出結論:int(m)
中的 m 表示在 zerofill
修飾時,數字長度不足 m 時前綴補充的 0 的個數,除此之外,兩者使用時沒有任何區別。
3. double(m,n)
面試官: MySQL 中 double (m,n) 中的 m 和 n 有什么含義?
題目解析: 這道題容易和上題一起出現,混淆視聽,但是難度相對就簡單多了。
double(m,n)
、float(m,n)
以及 decimal(m,n)
中的 m 和 n 定義均相同,而且比較清晰:
- m:數據精度,即數據的總長度;
- n:小數點精度,即浮點數小數點后的長度。
- 舉例說明:
float(6,2)
表示最多能存儲 6 位長度的浮點數,并且小數點精度為 2。
實戰驗證下上述結論, 還是在之前創建的 mooc_demo
數據庫中創建一張測試表:
DROP TABLE IF EXISTS `test_float`;
CREATE TABLE `test_float` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '數據庫主鍵',
`num1` float(6,2) zerofill,
`num2` double(6,2) zerofill
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
繼續插入測試數據:
insert into test_float (num1, num2) values (1234.5678,1234.5678);
執行 select * from test_float;
查詢語句,查詢結果如圖:
如上圖所示,小數點 2 位之后的數據被截斷,符合 SQL 定義時的預期。
4. 小結
MySQL 基礎數據類型的知識學習可以從兩個方面入手,一點是基本語法,學習基礎語法的目的是能夠上手使用這些數據類型,另一點是如何選擇在合適的場景使用合適的數據類型,需要明確這種數據類型會占用多少的字節空間,數據類型的最小值和最大值是什么,選擇不同數據類型可能會存在什么樣的潛在問題。