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