MySQL全面瓦解3:數(shù)據(jù)類型介紹與分析

概述

MySQL支持很多數(shù)據(jù)類型,以便我們能在復(fù)雜的業(yè)務(wù)場(chǎng)景中支持各種各樣的數(shù)據(jù)格式,存儲(chǔ)適當(dāng)?shù)臄?shù)據(jù)內(nèi)容。我們?cè)谠O(shè)計(jì)數(shù)據(jù)庫時(shí),正確的使用數(shù)據(jù)庫類型對(duì)整個(gè)數(shù)據(jù)庫的整潔和高效,會(huì)有很大的幫助。

目前常用的數(shù)據(jù)類型大致上可以分為4大類:整數(shù)類型、浮點(diǎn)數(shù)類型、字符串(字符)類型、日期/時(shí)間類型。詳細(xì)如下

4大類 主要類型
整數(shù)類型 tinyint 、 smallint 、 mediumint 、 int 、 bigint
浮點(diǎn)數(shù)類型 float 、 double 、 decimal
字符串(字符)類型 char 、 varchar 、 tinyblob 、 blob 、 mediumblob 、 longblob 、tinytext 、 text 、 mediumtext 、 longtext
日期/時(shí)間類型 Date 、 DateTime 、 TimeStamp 、 Time 、 Year

數(shù)值類型

MySQL支持所有標(biāo)準(zhǔn)SQL數(shù)值數(shù)據(jù)類型,包括嚴(yán)格數(shù)值數(shù)據(jù)類型(INTEGER、SMALLINT、DECIMAL和NUMERIC),還有近似數(shù)值數(shù)據(jù)類型(FLOAT、REAL和DOUBLE PRECISION),所以MySQL中數(shù)據(jù)類型是豐富且完整的。

而作為SQL標(biāo)準(zhǔn)的擴(kuò)展,MySQL也支持整數(shù)類型TINYINT、MEDIUMINT和BIGINT。在下面的表格中,我們總結(jié)了5個(gè)整數(shù)類型的存儲(chǔ)大小和取值范圍。

類型 字節(jié)數(shù) 有符號(hào)值范圍 無符號(hào)值范圍 作用
TINYINT 1 byte (-128,127) (0,255) 小整數(shù)值
SMALLINT 2 bytes (-32 768,32 767) (0,65 535) 大整數(shù)值
MEDIUMINT 3 bytes (-8 388 608,8 388 607) (0,16 777 215) 大整數(shù)值
INT或INTEGER 4 bytes (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整數(shù)值
BIGINT 8 bytes (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 極大整數(shù)值

我們創(chuàng)建表賦予的類型默認(rèn)是有符號(hào)類型的,無符號(hào)的需要在類型需要后面跟上unsigned 標(biāo)記,上面的數(shù)據(jù)范圍是根據(jù)字節(jié)對(duì)應(yīng)二進(jìn)制換算,比如一個(gè)字節(jié)轉(zhuǎn)化為十進(jìn)制最大為255(11111111),最小為0(00000000),具體可以去查下二進(jìn)制表示相關(guān)資料。
測(cè)試一下:

mysql> create table tinyintdemo(
  tiny TINYINT,
  tinyunsi TINYINT UNSIGNED
);
Query OK, 0 rows affected

mysql> insert into tinyintdemo values(-128,-128);
1264 - Out of range value for column 'tinyunsi' at row 1
mysql> insert into tinyintdemo values(-128,0);
Query OK, 1 row affected

mysql> insert into tinyintdemo values(255,255);
1264 - Out of range value for column 'tiny' at row 1
mysql> insert into tinyintdemo values(127,255);
Query OK, 1 row affected

上面我們故意輸入不正確的值,無符號(hào)下我們輸入-128,默認(rèn)有符號(hào)情況下我們輸入255,都會(huì)提示 Out of range,超出范圍。

mysql> select *  from  tinyintdemo;
+------+----------+
| tiny | tinyunsi |
+------+----------+
| -128 |        0 |
|  127 |      255 |
+------+----------+
2 rows in set

另外需注意的點(diǎn):我們經(jīng)常在創(chuàng)建表的時(shí)候定義字段為int(n),比如int(11) , 或者bitint(19) , 其實(shí)這不是描述字段長(zhǎng)度的意思,在int(n)中,int占據(jù)的字節(jié)是固定4個(gè),所以他的范圍也固定是在 (-2 147 483 648,2 147 483 647) 之間,
并不會(huì)因?yàn)閚的長(zhǎng)度是多少而改變,而n的目的是為了表實(shí)顯示寬度用的,在顯示寬度不足的時(shí)候補(bǔ)充0。
再測(cè)試一下:

mysql> CREATE TABLE lengthdemo (
       `nor` int,
       `norlen` int(8),
       `norfill` int(8) zerofill
);
Query OK, 0 rows affected

mysql> insert into lengthdemo values(12345,12345,12345);
Query OK, 1 row affected

mysql> select * from lengthdemo;

+-------+--------+---------+
| nor   | norlen | norfill |
+-------+--------+---------+
| 12345 |  12345 |00012345 |
+-------+--------+---------+
1 row in set

mysql> show create table lengthdemo;
+------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                                   |
+------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| lengthdemo | CREATE TABLE `lengthdemo` (
  `nor` int(11) DEFAULT NULL,
  `norlen` int(8) DEFAULT NULL,
  `norfill` int(8) unsigned zerofill DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set

從這個(gè)執(zhí)行結(jié)果中,我們可以總結(jié)如下:

1、n的值不管填寫多少,int類型只占據(jù)4個(gè)字節(jié)。

2、如果設(shè)置了n的顯示寬度之后,再加上unsigned zerofill,顯示寬度不足的用0補(bǔ)足,超過則直接顯示完整數(shù)值。

3、加 zerofill屬性的字段,會(huì)默認(rèn)為 unsigned 無符號(hào)類型。

浮點(diǎn)類型

float數(shù)值類型表示單精度浮點(diǎn)數(shù)值,double數(shù)值類型表示雙精度浮點(diǎn)數(shù)值,float和double都是浮點(diǎn)型,而decimal是定點(diǎn)型。浮點(diǎn)型和定點(diǎn)型可以用類型名稱后加(M,D)來表示,M表示該值的總共長(zhǎng)度,D表示小數(shù)點(diǎn)后面的長(zhǎng)度,M和D又稱為精度和標(biāo)度。

float和double在不指定精度時(shí),默認(rèn)會(huì)按照實(shí)際的精度來顯示,而DECIMAL在不指定精度時(shí),默認(rèn)整數(shù)為10,小數(shù)為0。

類型 大小 有符號(hào)值范圍 無符號(hào)值范圍 作用
FLOAT 4 bytes (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) 0,(1.175 494 351 E-38,3.402 823 466 E+38) 單精度、浮點(diǎn)數(shù)值
DOUBLE 8 bytes (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 雙精度、浮點(diǎn)數(shù)值
DECIMAL 對(duì)DECIMAL(M,D) ,如果M>D,為M+2否則為D+2 依賴于M和D的值 依賴于M和D的值 小數(shù)值

浮點(diǎn)型和定點(diǎn)型可以用類型名稱后加(M,D)來表示,M表示該值的總共長(zhǎng)度,D表示小數(shù)點(diǎn)后面的長(zhǎng)度,M和D又稱為精度和標(biāo)度。

float和double在不指定精度時(shí),默認(rèn)會(huì)按照實(shí)際的精度來顯示,而DECIMAL在不指定精度時(shí),默認(rèn)只取整數(shù),小數(shù)丟棄。

同樣的,我們來測(cè)試下三個(gè)類型的使用:

mysql> insert into accuracy values (1,1,1),(2.124,2.124,2.124),(3.125,3.125,3.125),(4.115,4.115,4.115),(5.136,5.136,5.136);
Query OK, 5 rows affected, 4 warnings (0.07 sec)
Records: 5  Duplicates: 0  Warnings: 4

mysql> select * from accuracy;
+------+------+------+
| a    | b    | c    |
+------+------+------+
| 1.00 | 1.00 | 1.00 |
| 2.12 | 2.12 | 2.12 |
| 3.12 | 3.12 | 3.13 |
| 4.12 | 4.12 | 4.12 |
| 5.14 | 5.14 | 5.14 |
+------+------+------+
5 rows in set (0.00 sec)

從這個(gè)執(zhí)行結(jié)果,總結(jié)如下:

1、c是decimal類型,采用的是四舍五入

2、a和b分別為float 和double,采用的是四舍六入五成雙

說明下四舍六入五成雙:5以下舍棄,5以上進(jìn)位,遇到5的時(shí)候,如果5后面還有不為0的任何數(shù)字,進(jìn)位,如果沒有,需要檢查5前面的數(shù)字,奇數(shù)進(jìn)位,偶數(shù)丟棄,觀察結(jié)果中 3.125和4.115,可以得到規(guī)律。

我們?cè)賹⒏↑c(diǎn)類型的(M,D)精度和標(biāo)度都去掉,結(jié)果如下:

mysql> create table accuracy2(a float,b double,c decimal);
Query OK, 0 rows affected

mysql> insert into accuracy2 values (1,1,1),(1.23,1.23,1.23);
Query OK, 2 rows affected
Records: 2  Duplicates: 0  Warnings: 1

mysql> select * from accuracy2;
+------+------+---+
| a    | b    | c |
+------+------+---+
|    1 |    1 | 1 |
| 1.23 | 1.23 | 1 |
+------+------+---+
2 rows in set

總結(jié)如下:

如果浮點(diǎn)數(shù)float、double如果不寫精度和標(biāo)度,則會(huì)按照實(shí)際的結(jié)果顯示,而decimal會(huì)將小數(shù)四舍五入,并且插入時(shí)發(fā)出警告信息。

float,double等非標(biāo)準(zhǔn)類型,在DB中保存的是近似值,而decimal則以字符串的形式保存準(zhǔn)確的數(shù)值,比如銀行、金融系統(tǒng)之類的對(duì)統(tǒng)計(jì)精度要求比較高的,建議采用decimal。

日期和時(shí)間類型

表示時(shí)間值的日期和時(shí)間類型為DATETIME、DATE、TIMESTAMP、TIME和YEAR。每個(gè)時(shí)間類型有一個(gè)有效值范圍和一個(gè)"零"值,當(dāng)指定不合法的MySQL不能表示的值時(shí)使用"零"值。

TIMESTAMP類型有專有的自動(dòng)更新特性,將在后面描述。

類型 大小 值范圍 格式 作用
DATE 3 bytes 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
TIME 3 bytes '-838:59:59'/'838:59:59' HH:MM:SS 時(shí)間值或持續(xù)時(shí)間
YEAR 1 bytes 1901/2155 YYYY 年份值
DATETIME 8 bytes 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和時(shí)間值
TIMESTAMP 4 bytes 1970-01-01 00:00:00/2038 結(jié)束時(shí)間是第 2147483647 秒,北京時(shí)間 2038-1-19 11:14:07,格林尼治時(shí)間 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和時(shí)間值,時(shí)間戳

字符串類型

字符串類型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。

類型 大小 作用
CHAR 0-255 bytes 定長(zhǎng)字符串
VARCHAR 0-65535 bytes 變長(zhǎng)字符串
TINYBLOB 0-255 bytes 不超過 255 個(gè)字符的二進(jìn)制字符串
TINYTEXT 0-255 bytes 短文本字符串
BLOB 0-65 535 bytes 二進(jìn)制形式的長(zhǎng)文本數(shù)據(jù)
TEXT 0-65 535 bytes 長(zhǎng)文本數(shù)據(jù)
MEDIUMBLOB 0-16 777 215 bytes 二進(jìn)制形式的中等長(zhǎng)度文本數(shù)據(jù)
MEDIUMTEXT 0-16 777 215 bytes 中等長(zhǎng)度文本數(shù)據(jù)
LONGBLOB 0-4 294 967 295 bytes 二進(jìn)制形式的極大文本數(shù)據(jù)
LONGTEXT 0-4 294 967 295 bytes 極大文本數(shù)據(jù)

注意點(diǎn):

1、CHAR(N) 和 VARCHAR(N) 中N代表字符的個(gè)數(shù),但并不代表字節(jié)個(gè)數(shù),比如 CHAR(10) 代表可以存儲(chǔ) 10 個(gè)字符。

2、CHAR 和VARCHAR類型類似,但它們保存和檢索的方式不同,最大長(zhǎng)度和是否尾部空格被保留等方面也不同,同時(shí)在存儲(chǔ)或檢索過程中不進(jìn)行大小寫轉(zhuǎn)換。

如果存放的數(shù)據(jù)為固定長(zhǎng)度的建議使用char類型,如:手機(jī)號(hào)碼、身份證等固定長(zhǎng)度的信息。

3、BINARY 和 VARBINARY 類似于 CHAR 和 VARCHAR,不同的是它們包含二進(jìn)制字符串而不要非二進(jìn)制字符串。它們包含字節(jié)字符串而不是字符字符串。這說明它們沒有字符集,并且排序和比較基于列值字節(jié)的數(shù)值。

4、BLOB是一個(gè)二進(jìn)制大對(duì)象,可以容納可變數(shù)量的數(shù)據(jù),包含4 種類型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB,區(qū)別是可容納存儲(chǔ)范圍不同。

5、TEXT 類型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。對(duì)應(yīng)的這 4 種 BLOB 類型,可存儲(chǔ)的最大長(zhǎng)度不同,可根據(jù)實(shí)際業(yè)務(wù)場(chǎng)景的選擇。

MySQL、Java類型對(duì)照

MySQL Type Name Return value ofGetColumnClassName Returned as Java Class
BIT(1) (new in MySQL-5.0) BIT java.lang.Boolean
BIT( > 1) (new in MySQL-5.0) BIT byte[]
TINYINT TINYINT java.lang.Boolean if the configuration property tinyInt1isBit is set to true (the default) and the storage size is 1,or java.lang.Integer if not.
BOOL, BOOLEAN TINYINT See TINYINT, above as these are aliases forTINYINT(1), currently.
SMALLINT[(M)][UNSIGNED] SMALLINT [UNSIGNED] java.lang.Integer (regardless if
UNSIGNED or not)
MEDIUMINT[(M)][UNSIGNED] MEDIUMINT [UNSIGNED] java.lang.Integer, if UNSIGNED java.lang.Long
INT,INTEGER[(M)][UNSIGNED] INTEGER [UNSIGNED] java.lang.Integer , if UNSIGNED java.lang.Long
BIGINT[(M)] [UNSIGNED] BIGINT [UNSIGNED] java.lang.Long , if UNSIGNED java.math.BigInteger
FLOAT[(M,D)] FLOAT java.lang.Float
DOUBLE[(M,B)] DOUBLE java.lang.Double
DECIMAL[(M[,D])] DECIMAL java.math.BigDecimala
DATE DATE java.sql.DateJa
DATETIME DATETIME java.sql.Timestamp
TIMESTAMP[(M)] TIMESTAMP java.sql.Timestamp
TIME TIME java.sql.Time
YEAR[(2|4)]公 YEAR眾 If yearIsDateType configuration property is set to false, then the returned object type is java.sql.Short . If set to true (the default) then an object of type java.sql.Date (with the date set to January 1st, at midnight).
CHAR(M) CHAR java.lang.String (unless the character set for the column is BINARY, then byte[] is returned.
VARCHAR(M) [BINARY] VARCHAR java.lang.String (unless the character set for the column is BINARY, then byte[] is returned.
BINARY(M) BINARY byte[]
VARBINARY(M) VARBINARY byte[]
TINYBLOB TINYBLOB byte[]
TINYTEXT VARCHAR java.lang.String
BLOB BLOB byte[]
MySQL Type Name Return value of GetColumnClassName Returned as Java Class
TEXT VARCHAR java.lang.String
MEDIUMBLOB MEDIUMBLOB byte[]
MEDIUMTEXT VARCHAR java.lang.String
LONGBLOB LONGBLOB byte[]
LONGTEXT VARCHAR java.lang.String
ENUM('value1','value2',...) CHAR java.lang.String
SET('value1','value2',...) CHAR java.lang.String

使用建議

不建議選擇較大的數(shù)值范圍,盡量選擇合適的數(shù)據(jù)范圍,越小的數(shù)據(jù)類型會(huì)更快,占用磁盤,內(nèi)存和CPU緩存也更小。

越簡(jiǎn)單的類型執(zhí)行的成本越低,比如整型比字符類型操作代價(jià)要小得多,很多固定范圍的文本內(nèi)容字段可以用整型表示。

盡量制定列為NOT NULL,有NULL的列值會(huì)使得索引、索引統(tǒng)計(jì)和值比較更加復(fù)雜。

浮點(diǎn)類型的建議統(tǒng)一選擇decimal,精度會(huì)好很多。

記錄時(shí)間的建議使用時(shí)間戳格式,存儲(chǔ)方便,索引高效

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容