數據類型和所占字節數


 

(data_type)是指系統中所允許的數據的類型。MySQL 數據類型定義了列中可以存儲什么數據以及該數據怎樣存儲的規則。

數據庫中的每個列都應該有適當的數據類型,用於限制或允許該列中存儲的數據。例如,列中存儲的為數字,則相應的數據類型應該為數值類型。

如果使用錯誤的數據類型可能會嚴重影響應用程序的功能和性能,所以在設計表時,應該特別重視數據列所用的數據類型。更改包含數據的列不是一件小事,這樣做可能會導致數據丟失。因此,在創建表時必須為每個列設置正確的數據類型和長度。

MySQL 的數據類型有大概可以分為 5 種,分別是整數類型、浮點數類型和定點數類型、日期和時間類型、字符串類型、二進制類型等。

注意:整數類型和浮點數類型可以統稱為數值數據類型。

1) 數值類型

整數類型包括 TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,浮點數類型包括 FLOAT 和 DOUBLE,定點數類型為 DECIMAL。

2) 日期/時間類型

包括 YEAR、TIME、DATE、DATETIME 和 TIMESTAMP。

3) 字符串類型

包括 CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM 和 SET 等。

4) 二進制類型

包括 BIT、BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。

定義字段的數據類型對數據庫的優化是十分重要的。

數值類型-整型:

MySQL 提供了多種數值型數據類型,不同的數據類型提供不同的取值范圍,可以存儲的值范圍越大,所需的存儲空間也會越大。

MySQL 主要提供的整數類型有 TINYINTSMALLINTMEDIUMINTINTBIGINT,其屬性字段可以添加 AUTO_INCREMENT 自增約束條件。下表中列出了 MySQL 中的數值類型。

類型名稱 說明 存儲需求
TINYINT 很小的整數 1個字節
SMALLINT 小的整數 2個宇節
MEDIUMINT 中等大小的整數 3個字節
INT (INTEGHR) 普通大小的整數 4個字節
BIGINT 大整數 8個字節


從上表中可以看到,不同類型的整數存儲所需的字節數不相同,占用字節數最小的是 TINYINT 類型,占用字節最大的是 BIGINT 類型,占用的字節越多的類型所能表示的數值范圍越大。

根據占用字節數可以求出每一種數據類型的取值范圍。例如,TINYINT 需要 1 個字節(8bit)來存儲,那么 TINYINT 無符號數的最大值為 28-1,即 255;TINYINT 有符號數的最大值為 27-1,即 127。其他類型的整數的取值范圍計算方法相同,如下表所示。

類型名稱 說明 存儲需求
TINYINT -128〜127 0 〜255
SMALLINT -32768〜32767 0〜65535
MEDIUMINT -8388608〜8388607 0〜16777215
INT (INTEGER) -2147483648〜2147483647 0〜4294967295
BIGINT -9223372036854775808〜9223372036854775807 0〜18446744073709551615
提示:顯示寬度和數據類型的取值范圍是無關的。顯示寬度只是指明 MySQL 最大可能顯示的數字個數,數值的位數小於指定的寬度時會由空格填充。如果插入了大於顯示寬度的值,只要該值不超過該類型整數的取值范圍,數值依然可以插入,而且能夠顯示出來。例如,year 字段插入 19999,當使用 SELECT 查詢該列值的時候,MySQL 顯示的將是完整的帶有 5 位數字的 19999,而不是 4 位數字的值。

其他整型數據類型也可以在定義表結構時指定所需的顯示寬度,如果不指定,則系統為每一種類型指定默認的寬度值。

不同的整數類型有不同的取值范圍,並且需要不同的存儲空間,因此應根據實際需要選擇最合適的類型,這樣有利於提高查詢的效率和節省存儲空間。

 

數值類型-小數型

浮點類型有兩種,分別是單精度浮點數(FLOAT)和雙精度浮點數(DOUBLE);定點類型只有一種,就是 DECIMAL

浮點類型和定點類型都可以用(M, D)來表示,其中M稱為精度,表示總共的位數;D稱為標度,表示小數的位數。

浮點數類型的取值范圍為 M(1~255)和 D(1~30,且不能大於 M-2),分別表示顯示寬度和小數位數。M 和 D 在 FLOAT 和DOUBLE 中是可選的,FLOAT 和 DOUBLE 類型將被保存為硬件所支持的最大精度。DECIMAL 的默認 D 值為 0、M 值為 10。

下表中列出了 MySQL 中的小數類型和存儲需求。

類型名稱 說明 存儲需求
FLOAT 單精度浮點數 4 個字節
DOUBLE 雙精度浮點數 8 個字節
DECIMAL (M, D),DEC 壓縮的“嚴格”定點數 M+2 個字節


DECIMAL 類型不同於 FLOAT 和 DOUBLE。DOUBLE 實際上是以字符串的形式存放的,DECIMAL 可能的最大取值范圍與 DOUBLE 相同,但是有效的取值范圍由 M 和 D 決定。如果改變 M 而固定 D,則取值范圍將隨 M 的變大而變大。

從上表中可以看到,DECIMAL 的存儲空間並不是固定的,而由精度值 M 決定,占用 M+2 個字節。

FLOAT 類型的取值范圍如下:

  • 有符號的取值范圍:-3.402823466E+38~-1.175494351E-38。
  • 無符號的取值范圍:0 和 -1.175494351E-38~-3.402823466E+38。


DOUBLE 類型的取值范圍如下:

  • 有符號的取值范圍:-1.7976931348623157E+308~-2.2250738585072014E-308。
  • 無符號的取值范圍:0 和 -2.2250738585072014E-308~-1.7976931348623157E+308。
提示:不論是定點還是浮點類型,如果用戶指定的精度超出精度范圍,則會四舍五入進行處理。

FLOAT 和 DOUBLE 在不指定精度時,默認會按照實際的精度(由計算機硬件和操作系統決定),DECIMAL 如果不指定精度,默認為(10,0)。

浮點數相對於定點數的優點是在長度一定的情況下,浮點數能夠表示更大的范圍;缺點是會引起精度問題。

最后再強調一下:在 MySQL 中,定點數以字符串形式存儲,在對精度要求比較高的時候(如貨幣、科學數據),使用 DECIMAL 的類型比較好,另外兩個浮點數進行減法和比較運算時也容易出問題,所以在使用浮點數時需要注意,並盡量避免做浮點數比較。

 

日期/時間類型:

MySQL 中有多處表示日期的數據類型:YEARTIMEDATEDTAETIMETIMESTAMP。當只記錄年信息的時候,可以只使用 YEAR 類型。

每一個類型都有合法的取值范圍,當指定確定不合法的值時,系統將“零”值插入數據庫中。

下表中列出了 MySQL 中的日期與時間類型。

類型名稱 日期格式 日期范圍 存儲需求
YEAR YYYY 1901 ~ 2155 1 個字節
TIME HH:MM:SS -838:59:59 ~ 838:59:59 3 個字節
DATE YYYY-MM-DD 1000-01-01 ~ 9999-12-3 3 個字節
DATETIME YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 8 個字節
TIMESTAMP YYYY-MM-DD HH:MM:SS 1980-01-01 00:00:01 UTC ~ 2040-01-19 03:14:07 UTC 4 個字節

YEAR 類型

YEAR 類型是一個單字節類型,用於表示年,在存儲時只需要 1 個字節。可以使用各種格式指定 YEAR,如下所示:

  • 以 4 位字符串或者 4 位數字格式表示的 YEAR,范圍為 '1901'~'2155'。輸入格式為 'YYYY' 或者 YYYY,例如,輸入 '2010' 或 2010,插入數據庫的值均為 2010。
  • 以 2 位字符串格式表示的 YEAR,范圍為 '00' 到 '99'。'00'~'69' 和 '70'~'99' 范圍的值分別被轉換為 2000~2069 和 1970~1999 范圍的 YEAR 值。'0' 與 '00' 的作用相同。插入超過取值范圍的值將被轉換為 2000。
  • 以 2 位數字表示的 YEAR,范圍為 1~99。1~99 和 70~99 范圍的值分別被轉換為 2001~2069 和 1970~1999 范圍的 YEAR 值。注意,在這里 0 值將被轉換為 0000,而不是 2000。

提示:兩位整數范圍與兩位字符串范圍稍有不同。例如,插入 3000 年,讀者可能會使用數字格式的 0 表示 YEAR,實際上,插入數據庫的值為 0000,而不是所希望的 3000。只有使用字符串格式的 '0' 或 '00',才可以被正確解釋為 3000,非法 YEAR值將被轉換為 0000。

TIME 類型

TIME 類型用於只需要時間信息的值,在存儲時需要 3 個字節。格式為 HH:MM:SS。HH 表示小時,MM 表示分鍾,SS 表示秒。

TIME 類型的取值范圍為 -838:59:59~838:59:59,小時部分如此大的原因是 TIME 類型不僅可以用於表示一天的時間(必須小於 24 小時),還可能是某個事件過去的時間或兩個事件之間的時間間隔(可大於 24 小時,或者甚至為負)。

可以使用各種格式指定 TIME 值,如下所示。

  • 'D HH:MM:SS' 格式的字符串。還可以使用這些“非嚴格”的語法:'HH:MM:SS'、'HH:MM'、'D HH' 或 'SS'。這里的 D 表示日,可以取 0~34 之間的值。在插入數據庫時,D 被轉換為小時保存,格式為 “D*24+HH”。
  • 'HHMMSS' 格式、沒有間隔符的字符串或者 HHMMSS 格式的數值,假定是有意義的時間。例如,'101112' 被理解為'10:11:12',但是 '106112' 是不合法的(它有一個沒有意義的分鍾部分),在存儲時將變為 00:00:00。

提示:為 TIME 列分配簡寫值時應注意:如果沒有冒號,MySQL 解釋值時,假定最右邊的兩位表示秒。(MySQL 解釋 TIME 值為過去的時間而不是當前的時間)。例如,讀者可能認為 '1112' 和 1112 表示 11:12:00(即 11 點過 12 分鍾),但MySQL 將它們解釋為 00:11:12(即 11 分 12 秒)。同樣 '12' 和 12 被解釋為00:00:12。相反,TIME 值中如果使用冒號則肯定被看作當天的時間,也就是說,'11:12' 表示 11:12:00,而不是 00:11:12。

DATE 類型

DATE 類型用於僅需要日期值時,沒有時間部分,在存儲時需要 3 個字節。日期格式為 'YYYY-MM-DD',其中 YYYY 表示年,MM 表示月,DD 表示日。

在給 DATE 類型的字段賦值時,可以使用字符串類型或者數字類型的數據插入,只要符合 DATE 的日期格式即可。如下所示:

  • 以 'YYYY-MM-DD' 或者 'YYYYMMDD' 字符中格式表示的日期,取值范圍為 '1000-01-01'~'9999-12-3'。例如,輸入 '2015-12-31' 或者 '20151231',插入數據庫的日期為2015-12-31。
  • 以 'YY-MM-DD' 或者 'YYMMDD' 字符串格式表示日期,在這里YY表示兩位的年值。MySQL 解釋兩位年值的規則:'00~69' 范圍的年值轉換為 '2000~2069','70~99' 范圍的年值轉換為 '1970~1999'。例如,輸入 '15-12-31',插入數據庫的日期為 2015-12-31;輸入 '991231',插入數據庫的日期為 1999-12-31。
  • 以 YYMMDD 數字格式表示的日期,與前面相似,00~69 范圍的年值轉換為 2000~2069,80~99 范圍的年值轉換為 1980~1999。例如,輸入 151231,插入數據庫的日期為 2015-12-31,輸入 991231,插入數據庫的日期為 1999-12-31。
  • 使用 CURRENT_DATE 或者 NOW(),插入當前系統日期。

提示:MySQL 允許“不嚴格”語法:任何標點符號都可以用作日期部分之間的間隔符。例如,'98-11-31'、'98.11.31'、'98/11/31'和'98@11@31' 是等價的,這些值也可以正確地插入數據庫。

DATETIME 類型

DATETIME 類型用於需要同時包含日期和時間信息的值,在存儲時需要 8 個字節。日期格式為 'YYYY-MM-DD HH:MM:SS',其中 YYYY 表示年,MM 表示月,DD 表示日,HH 表示小時,MM 表示分鍾,SS 表示秒。

在給 DATETIME 類型的字段賦值時,可以使用字符串類型或者數字類型的數據插入,只要符合 DATETIME 的日期格式即可,如下所示。

  • 以 'YYYY-MM-DD HH:MM:SS' 或者 'YYYYMMDDHHMMSS' 字符串格式表示的日期,取值范圍為 '1000-01-01 00:00:00'~'9999-12-3 23:59:59'。例如,輸入 '2014-12-31 05:05:05' 或者 '20141231050505’,插入數據庫的 DATETIME 值都為 2014-12-31 05:05:05。
  • 以 'YY-MM-DD HH:MM:SS' 或者 'YYMMDDHHMMSS' 字符串格式表示的日期,在這里 YY 表示兩位的年值。與前面相同,'00~79' 范圍的年值轉換為 '2000~2079','80~99' 范圍的年值轉換為 '1980~1999'。例如,輸入 '14-12-31 05:05:05',插入數據庫的 DATETIME 為 2014-12-31 05:05:05;輸入 141231050505,插入數據庫的 DATETIME 為 2014-12-31 05:05:05。
  • 以 YYYYMMDDHHMMSS 或者 YYMMDDHHMMSS 數字格式表示的日期和時間。例如,輸入 20141231050505,插入數據庫的 DATETIME 為 2014-12-31 05:05:05;輸入 140505050505,插入數據庫的 DATETIME 為 2014-12-31 05:05:05。

提示:MySQL 允許“不嚴格”語法:任何標點符號都可用作日期部分或時間部分之間的間隔符。例如,'98-12-31 11:30:45'、'98.12.31 11+30+35'、'98/12/31 11*30*45' 和 '98@12@31 11^30^45' 是等價的,這些值都可以正確地插入數據庫。

TIMESTAMP 類型

TIMESTAMP 的顯示格式與 DATETIME 相同,顯示寬度固定在 19 個字符,日期格式為 YYYY-MM-DD HH:MM:SS,在存儲時需要 4 個字節。但是 TIMESTAMP 列的取值范圍小於 DATETIME 的取值范圍,為 '1970-01-01 00:00:01'UTC~'2038-01-19 03:14:07'UTC。在插入數據時,要保證在合法的取值范圍內。

提示:協調世界時(英:Coordinated Universal Time,法:Temps Universel Coordonné)又稱為世界統一時間、世界標准時間、國際協調時間。英文(CUT)和法文(TUC)的縮寫不同,作為妥協,簡稱 UTC。

TIMESTAMP 與 DATETIME 除了存儲字節和支持的范圍不同外,還有一個最大的區別是:

  • DATETIME 在存儲日期數據時,按實際輸入的格式存儲,即輸入什么就存儲什么,與時區無關;
  • 而 TIMESTAMP 值的存儲是以 UTC(世界標准時間)格式保存的,存儲時對當前時區進行轉換,檢索時再轉換回當前時區。即查詢時,根據當前時區的不同,顯示的時間值是不同的。

提示:如果為一個 DATETIME 或 TIMESTAMP 對象分配一個 DATE 值,結果值的時間部分被設置為 '00:00:00',因此 DATE 值未包含時間信息。如果為一個 DATE 對象分配一個 DATETIME 或 TIMESTAMP 值,結果值的時間部分被刪除,因此DATE 值未包含時間信息。

 

字符串類型:

字符串類型用來存儲字符串數據,還可以存儲圖片和聲音的二進制數據。字符串可以區分或者不區分大小寫的串比較,還可以進行正則表達式的匹配查找。

MySQL 中的字符串類型有 CHARVARCHARTINYTEXTTEXTMEDIUMTEXTLONGTEXTENUMSET 等。

下表中列出了 MySQL 中的字符串數據類型,括號中的M表示可以為其指定長度。

類型名稱 說明 存儲需求
CHAR(M) 固定長度非二進制字符串 M 字節,1<=M<=255
VARCHAR(M) 變長非二進制字符串 L+1字節,在此,L< = M和 1<=M<=255
TINYTEXT 非常小的非二進制字符串 L+1字節,在此,L<2^8
TEXT 小的非二進制字符串 L+2字節,在此,L<2^16
MEDIUMTEXT 中等大小的非二進制字符串 L+3字節,在此,L<2^24
LONGTEXT 大的非二進制字符串 L+4字節,在此,L<2^32
ENUM 枚舉類型,只能有一個枚舉字符串值 1或2個字節,取決於枚舉值的數目 (最大值為65535)
SET 一個設置,字符串對象可以有零個或 多個SET成員 1、2、3、4或8個字節,取決於集合 成員的數量(最多64個成員)


VARCHAR 和 TEXT 類型是變長類型,其存儲需求取決於列值的實際長度(在前面的表格中用 L 表示),而不是取決於類型的最大可能尺寸。

例如,一個 VARCHAR(10) 列能保存一個最大長度為 10 個字符的字符串,實際的存儲需要字符串的長度 L 加上一個字節以記錄字符串的長度。對於字符 “abcd”,L 是 4,而存儲要求 5 個字節。

CHAR 和 VARCHAR 類型

CHAR(M) 為固定長度字符串,在定義時指定字符串列長。當保存時,在右側填充空格以達到指定的長度。M 表示列的長度,范圍是 0~255 個字符。

例如,CHAR(4) 定義了一個固定長度的字符串列,包含的字符個數最大為 4。當檢索到 CHAR 值時,尾部的空格將被刪除。

VARCHAR(M) 是長度可變的字符串,M 表示最大列的長度,M 的范圍是 0~65535。VARCHAR 的最大實際長度由最長的行的大小和使用的字符集確定,而實際占用的空間為字符串的實際長度加 1。

例如,VARCHAR(50) 定義了一個最大長度為 50 的字符串,如果插入的字符串只有 10 個字符,則實際存儲的字符串為 10 個字符和一個字符串結束字符。VARCHAR 在值保存和檢索時尾部的空格仍保留。

【實例】下面將不同的字符串保存到 CHAR(4) 和 VARCHAR(4) 列,說明 CHAR 和 VARCHAR 之間的差別,如下表所示。

插入值 CHAR(4) 存儲需求 VARCHAR(4) 存儲需求
' ' '    ' 4字節 '' 1字節
'ab' 'ab  ' 4字節 'ab' 3字節
'abc' 'abc ' 4字節 'abc' 4字節
'abcd' 'abcd' 4字節 'abcd' 5字節
'abcdef' 'abcd' 4字節 'abcd' 5字節


對比結果可以看到,CHAR(4) 定義了固定長度為 4 的列,無論存入的數據長度為多少,所占用的空間均為 4 個字節。VARCHAR(4) 定義的列所占的字節數為實際長度加 1。

TEXT 類型

TEXT 列保存非二進制字符串,如文章內容、評論等。當保存或查詢 TEXT 列的值時,不刪除尾部空格。

TEXT 類型分為 4 種:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。不同的 TEXT 類型的存儲空間和數據長度不同。

  • TINYTEXT 表示長度為 255(28-1)字符的 TEXT 列。
  • TEXT 表示長度為 65535(216-1)字符的 TEXT 列。
  • MEDIUMTEXT 表示長度為 16777215(224-1)字符的 TEXT 列。
  • LONGTEXT 表示長度為 4294967295 或 4GB(232-1)字符的 TEXT 列。

ENUM 類型

ENUM 是一個字符串對象,值為表創建時列規定中枚舉的一列值。其語法格式如下:

<字段名> ENUM( '值1', '值1', …, '值n' )

字段名指將要定義的字段,值 n 指枚舉列表中第 n 個值。

ENUM 類型的字段在取值時,能在指定的枚舉列表中獲取,而且一次只能取一個。如果創建的成員中有空格,尾部的空格將自動被刪除。

ENUM 值在內部用整數表示,每個枚舉值均有一個索引值;列表值所允許的成員值從 1 開始編號,MySQL 存儲的就是這個索引編號,枚舉最多可以有 65535 個元素。

例如,定義 ENUM 類型的列('first','second','third'),該列可以取的值和每個值的索引如下表所示。

索引
NULL NULL
'' 0
’first 1
second 2
third 3


ENUM 值依照列索引順序排列,並且空字符串排在非空字符串前,NULL 值排在其他所有枚舉值前。

提示:ENUM 列總有一個默認值。如果將 ENUM 列聲明為 NULL,NULL 值則為該列的一個有效值,並且默認值為 NULL。如果 ENUM 列被聲明為 NOT NULL,其默認值為允許的值列表的第 1 個元素。

SET 類型

SET 是一個字符串的對象,可以有零或多個值,SET 列最多可以有 64 個成員,值為表創建時規定的一列值。指定包括多個 SET 成員的 SET 列值時,各成員之間用逗號,隔開,語法格式如下:

SET( '值1', '值2', …, '值n' )

與 ENUM 類型相同,SET 值在內部用整數表示,列表中每個值都有一個索引編號。當創建表時,SET 成員值的尾部空格將自動刪除。

但與 ENUM 類型不同的是,ENUM 類型的字段只能從定義的列值中選擇一個值插入,而 SET 類型的列可從定義的列值中選擇多個字符的聯合。

提示:如果插入 SET 字段中的列值有重復,則 MySQL 自動刪除重復的值;插入 SET 字段的值的順序並不重要,MySQL 會在存入數據庫時,按照定義的順序顯示;如果插入了不正確的值,默認情況下,MySQL 將忽視這些值,給出警告。

二進制類型:

MySQL 支持兩類字符型數據:文本字符串和二進制字符串。上節《MySQL字符串類型》我們講了文本字符串,這節我們來講解二進制字符串。

二進制字符串類型有時候也直接被稱為“二進制類型”。

MySQL 中的二進制字符串有 BITBINARYVARBINARYTINYBLOBBLOBMEDIUMBLOB 和 LONGBLOB

下表中列出了 MySQL 中的二進制數據類型,括號中的M表示可以為其指定長度。

類型名稱 說明 存儲需求
BIT(M) 位字段類型 大約 (M+7)/8 字節
BINARY(M) 固定長度二進制字符串 M 字節
VARBINARY (M) 可變長度二進制字符串 M+1 字節
TINYBLOB (M) 非常小的BLOB L+1 字節,在此,L<2^8
BLOB (M) 小 BLOB L+2 字節,在此,L<2^16
MEDIUMBLOB (M) 中等大小的BLOB L+3 字節,在此,L<2^24
LONGBLOB (M) 非常大的BLOB L+4 字節,在此,L<2^32

BIT 類型

位字段類型。M 表示每個值的位數,范圍為 1~64。如果 M 被省略,默認值為 1。如果為 BIT(M) 列分配的值的長度小於 M 位,在值的左邊用 0 填充。例如,為 BIT(6) 列分配一個值 b'101',其效果與分配 b'000101' 相同。

BIT 數據類型用來保存位字段值,例如以二進制的形式保存數據 13,13 的二進制形式為 1101,在這里需要位數至少為 4 位的 BIT 類型,即可以定義列類型為 BIT(4)。大於二進制 1111 的數據是不能插入 BIT(4) 類型的字段中的。

提示:默認情況下,MySQL 不可以插入超出該列允許范圍的值,因而插入數據時要確保插入的值在指定的范圍內。

BINARY 和 VARBINARY 類型

BINARY 和 VARBINARY 類型類似於 CHAR 和 VARCHAR,不同的是它們包含二進制字節字符串。使用的語法格式如下:

列名稱 BINARY(M) 或者 VARBINARY(M)

BINARY 類型的長度是固定的,指定長度后,不足最大長度的,將在它們右邊填充 “\0” 補齊,以達到指定長度。例如,指定列數據類型為 BINARY(3),當插入 a 時,存儲的內容實際為 “\a0\0”,當插入 ab 時,實際存儲的內容為“ab\0”,無論存儲的內容是否達到指定的長度,存儲空間均為指定的值 M。

VARBINARY 類型的長度是可變的,指定好長度之后,長度可以在 0 到最大值之間。例如,指定列數據類型為 VARBINARY(20),如果插入的值長度只有 10,則實際存儲空間為 10 加 1,實際占用的空間為字符串的實際長度加 1。

BLOB 類型

BLOB 是一個二進制的對象,用來存儲可變數量的數據。BLOB 類型分為 4 種:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB,它們可容納值的最大長度不同,如下表所示。

數據類型 存儲范圍
TINYBLOB 最大長度為255 (28-1)字節
BLOB 最大長度為65535 (216-1)字節
MEDIUMBLOB 最大長度為16777215 (224-1)字節
LONGBLOB 最大長度為4294967295或4GB (231-1)字節


BLOB 列存儲的是二進制字符串(字節字符串),TEXT 列存儲的是非進制字符串(字符字符串)。BLOB 列是字符集,並且排序和比較基於列值字節的數值;TEXT 列有一個字符集,並且根據字符集對值進行排序和比較。

 

數據類型的選擇

MySQL 提供了大量的數據類型,為了優化存儲和提高數據庫性能,在任何情況下都應該使用最精確的數據類型。
 
前面主要對 MySQL 中的數據類型及其基本特性進行了描述,包括它們能夠存放的值的類型和占用空間等。本節主要討論創建數據庫表時如何選擇數據類型。
 
可以說字符串類型是通用的數據類型,任何內容都可以保存在字符串中,數字和日期都可以表示成字符串形式。
 
但是也不能把所有的列都定義為字符串類型。對於數值類型,如果把它們設置為字符串類型的,會使用很多的空間。並且在這種情況下使用數值類型列來存儲數字,比使用字符串類型更有效率。
 
另外需要注意的是,由於對數字和字符串的處理方式不同,查詢結果也會存在差異。例如,對數字的排序與對字符串的排序是不一樣的。
 
例如,數字 2 小於數字 11,但字符串 '2' 卻比字符串 '11' 大。此問題可以通過把列放到數字上下文中來解決,如下面 SQL 語句:

SELECT course+ 0 as num ... ORDER BY num;

讓 course 列加上 0,可以強制列按數字的方式來排序,但這么做很明顯是不合理的。
 
如果讓 MySQL 把一個字符串列當作一個數字列來對待,會引發很嚴重的問題。這樣做會迫使讓列里的每一個值都執行從字符串到數字的轉換,操作效率低。而且在計算過程中使用這樣的列,會導致 MySQL 不會使用這些列上的任何索引,從而進一步降低查詢的速度。
 
所以我們在選擇數據類型時要考慮存儲、查詢和整體性能等方面的問題。
 
在選擇數據類型時,首先要考慮這個列存放的值是什么類型的。一般來說,用數值類型列存儲數字、用字符類型列存儲字符串、用時態類型列存儲日期和時間。

數值類型

對於數值類型列,如果要存儲的數字是整數(沒有小數部分),則使用整數類型;如果要存儲的數字是小數(帶有小數部分),則可以選用 DECIMAL 或浮點類型,但是一般選擇 FLOAT 類型(浮點類型的一種)。

例如,如果列的取值范圍是 1~99999 之間的整數,則 MEDIUMINT UNSIGNED 類型是最好的選擇。

MEDIUMINT 是整數類型,UNSIGNED 用來將數字類型無符號化。比如 INT 類型的取值范圍是 -2 147 483 648 ~ 2 147 483 647,那么 INT UNSIGNED 類型的取值范圍就是 0 ~ 4 294 967 295。

如果需要存儲某些整數值,則值的范圍決定了可選用的數據類型。如果取值范圍是 0~1000,那么可以選擇 SMALLINT~BIGINT 之間的任何一種類型。如果取值范圍超過了 200 萬,則不能使用 SMALLINT,可以選擇的類型變為從 MEDIUMINT 到 BIGINT 之間的某一種。
 
當然,完全可以為要存儲的值選擇一種最“大”的數據類型。但是,如果正確選擇數據類型,不僅可以使表的存儲空間變小,也會提高性能。因為與較長的列相比,較短的列的處理速度更快。當讀取較短的值時,所需的磁盤讀寫操作會更少,並且可以把更多的鍵值放入內存索引緩沖區里。
 
如果無法獲知各種可能值的范圍,則只能靠猜測,或者使用 BIGINT 以滿足最壞情況的需要。如果猜測的類型偏小,那么也不是就無葯可救。將來,還可以使用 ALTER TABLE 讓該列變得更大些。
 
如果數值類型需要存儲的數據為貨幣,如人民幣。在計算時,使用到的值常帶有元和分兩個部分。它們看起來像是浮點值,但 FLOAT 和 DOUBLE 類型都存在四舍五入的誤差問題,因此不太適合。因為人們對自己的金錢都很敏感,所以需要一個可以提供完美精度的數據類型。
 
可以把貨幣表示成 DECIMAL(M,2) 類型,其中 M 為所需取值范圍的最大寬度。這種類型的數值可以精確到小數點后 2 位。DECIMAL 的優點在於不存在舍入誤差,計算是精確的。
 
對於電話號碼、信用卡號和社會保險號都會使用非數字字符。因為空格和短划線不能直接存儲到數字類型列里,除非去掉其中的非數字字符。但即使去掉了其中的非數字字符,也不能把它們存儲成數值類型,以避免丟失開頭的“零”。

日期和時間類型

MySQL 對於不同種類的日期和時間都提供了數據類型,比如 YEAR 和 TIME。如果只需要記錄年份,則使用 YEAR 類型即可;如果只記錄時間,可以使用 TIME 類型。
 
如果同時需要記錄日期和時間,則可以使用 TIMESTAMP 或者 DATETIME 類型。由於TIMESTAMP 列的取值范圍小於 DATETIME 的取值范圍,因此存儲較大的日期最好使用 DATETIME。
 
TIMESTAMP 也有一個 DATETIME 不具備的屬性。默認情況下,當插入一條記錄但並沒有指定 TIMESTAMP 這個列值時,MySQL 會把 TIMESTAMP 列設為當前的時間。因此當需要插入記錄和當前時間時,使用 TIMESTAMP 是方便的,另外 TIMESTAMP 在空間上比 DATETIME 更有效。
 
MySQL 沒有提供時間部分為可選的日期類型。DATE 沒有時間部分,DATETIME 必須有時間部分。如果時間部分是可選的,那么可以使用 DATE 列來記錄日期,再用一個單獨的 TIME 列來記錄時間。然后,設置 TIME 列可以為 NULL。SQL 語句如下:

CREATE TABLE mytb1 (
    date DATE NOT NULL,  #日期是必需的
    time TIME NULL  #時間可選(可能為NULL)
);

字符串類型

字符串類型沒有像數字類型列那樣的“取值范圍",但它們都有長度的概念。如果需要存儲的字符串短於 256 個字符,那么可以使用 CHAR、VARCHAR 或 TINYTEXT。如果需要存儲更長一點的字符串,則可以選用 VARCHAR 或某種更長的 TEXT 類型。
 
如果某個字符串列用於表示某種固定集合的值,那么可以考慮使用數據類型 ENUM 或 SET。

CHAR 和 VARCHAR 之間的特點和選擇

CHAR 和 VARCHAR 的區別如下:

  • CHAR 是固定長度字符,VARCHAR 是可變長度字符。
  • CHAR 會自動刪除插入數據的尾部空格,VARCHAR 不會刪除尾部空格。

 
CHAR 是固定長度,所以它的處理速度比 VARCHAR 的速度要快,但是它的缺點就是浪費存儲空間。所以對存儲不大,但在速度上有要求的可以使用 CHAR 類型,反之可以使用 VARCHAR類型來實現。
 
存儲引擎對於選擇 CHAR 和 VARCHAR 的影響:

  • 對於 MyISAM 存儲引擎,最好使用固定長度的數據列代替可變長度的數據列。這樣可以使整個表靜態化,從而使數據檢索更快,用空間換時間。
  • 對於InnoDB存儲引擎,最好使用可變長度的數據列,因為 InnoDB 數據表的存儲格式不分固定長度和可變長度,因此使用 CHAR 不一定比使用 VARCHAR 更好,但由於 VARCHAR 是按照實際的長度存儲,比較節省空間,所以對磁盤 I/O 和數據存儲總量比較好。

ENUM 和 SET

ENUM 只能取單值,它的數據列表是一個枚舉集合。它的合法取值列表最多允許有 65 535個成員。因此,在需要從多個值中選取一個時,可以使用 ENUM。比如,性別字段適合定義,為 ENUM 類型,每次只能從‘男’或‘女’中取一個值。
 
SET 可取多值。它的合法取值列表最多允許有 64 個成員。空字符串也是一個合法的 SET值。在需要取多個值的時候,適合使用 SET 類型,比如,要存儲一個人興趣愛好,最好使用SET類型。
 
ENUM 和 SET 的值是以字符串形式出現的,但在內部,MySQL 以數值的形式存儲它們。

二進制類型

BLOB 是二進制字符串,TEXT 是非二進制字符串,兩者均可存放大容量的信息。BLOB 主要存儲圖片、音頻信息等,而 TEXT 只能存儲純文本文件。

轉載地址:http://c.biancheng.net/view/7175.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM