MYSQL裏的BLOB數據類型
BLOB是一個二進制大對象,用來存儲可變數量的數據。BLOB類型分爲4種:TinyBlob、Blob、MediumBlob、LongBlob,
這幾個類型之間的唯一區別是在存儲文件的最大大小上不同。
MySQL的四種BLOB類型 類型 大小(單位:字節)
TinyBlob 最大 255
Blob 最大 65K
MediumBlob 最大 16M
LongBlob 最大 4G
BLOB列存儲的是二進制字符串(字節字符串);TEXT列存儲的是非二進制字符串(字符字符串)。
BLOB列沒有字符集,並且排序和比較基於列值字節的數值;TEXT列有一個字符集,並且根據字符集對值進行排序和比較
BLOB是二進制字符串,TEXT是非二進制字符串,兩者均可存放大容量的信息。BLOB主要存儲圖片、音頻信息等,
而TEXT只能存儲文本文件。
SQLSERVER
SQLSERVER並沒有BLOB數據類型,只有大型對象數據類型(BLOB):
text,ntext,image,nvarchar(max),varchar(max),varbinary(max)和xml數據類型
這些數據類型的數據都存放在LOB類型的數據頁面裏
如有不對的地方,歡迎大家拍磚o(∩_∩)o
其他類型
第11章:列類型
目錄
MySQL支持多種列類型:數值類型、日期/時間類型和字符串(字符)類型。本章首先對這些列類型進行了概述,然後更加詳細地描述了各種列的類型,以及列類型存儲需求的總結。概述很簡單。關於具體列類型的詳細信息應查閱詳細的描述,例如指定值時允許使用的格式。
MySQL支持處理空間數據的擴展名。關於空間類型的信息參見第19章:MySQL中的空間擴展。
幾種列類型描述使用了下述慣例:
· M
表示最大顯示寬度。最大有效顯示寬度是255。
· D
適用於浮點和定點類型,並表示小數點後面的位數。最大可能的值是30,但不應大於M-2。
· 方括號(‘[’和‘]’)表示可選部分。
下面爲數值列類型的概述。詳細信息參見11.2節,“數值類型”。列存儲需求參見11.5節,“列類型存儲需求”。
M指示最大顯示寬度。最大有效顯示寬度是255。顯示寬度與存儲大小或類型包含的值的範圍無關,相關描述見11.2節,“數值類型”。
如果爲一個數值列指定ZEROFILL,MySQL自動爲該列添加UNSIGNED屬性。
SERIAL是BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE的一個別名。
在整數列定義中,SERIAL DEFAULT VALUE是NOT NULL AUTO_INCREMENT UNIQUE的一個別名。
警告:應當清楚,當使用在整數值(其中一個是UNSIGNED類型)之間使用減號時,結果是無符號。參見12.8節,“Cast函數和操作符”。
· BIT[(M)]
位字段類型。M表示每個值的位數,範圍爲從1到64。如果M被省略, 默認爲1。
· TINYINT[(M)] [UNSIGNED] [ZEROFILL]
很小的整數。帶符號的範圍是-128到127。無符號的範圍是0到255。
· BOOL,BOOLEAN
是TINYINT(1)的同義詞。zero值被視爲假。非zero值視爲真。
在將來,將根據標準SQL引入完全布爾類型的處理。
· SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
小的整數。帶符號的範圍是-32768到32767。無符號的範圍是0到65535。
· MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
中等大小的整數。帶符號的範圍是-8388608到8388607。無符號的範圍是0到16777215。
· INT[(M)] [UNSIGNED] [ZEROFILL]
普通大小的整數。帶符號的範圍是-2147483648到2147483647。無符號的範圍是0到4294967295。
· INTEGER[(M)] [UNSIGNED] [ZEROFILL]
這是INT的同義詞。
· BIGINT[(M)] [UNSIGNED] [ZEROFILL]
大整數。帶符號的範圍是-9223372036854775808到9223372036854775807。無符號的範圍是0到18446744073709551615。
應清楚BIGINT列的下述內容:
o 使用帶符號的BIGINT或DOUBLE值進行所有算法,因此除了位函數,不應使用大於9223372036854775807(63位)的無符號的大整數! 如果這樣做,結果中的最後幾位可能出錯,這是由於將BIGINT值轉換爲DOUBLE進行四捨五入時造成的錯誤。
MySQL可以在以下情況下處理BIGINT:
§ 當使用整數在一個BIGINT列保存大的無符號的值時。
§ 在MIN(col_name)或MAX(col_name)中,其中col_name指BIGINT列。
§ 使用操作符(+,-,*等等)並且兩個操作數均爲整數時。
o 總是可以使用一個字符串在BIGINT列中保存嚴格整數值。在這種情況下,MySQL執行字符串-數字轉換,其間不存在雙精度表示。
o 當兩個操作數均爲整數值時,-、+和* 操作符使用BIGINT算法。這說明如果乘兩個大整數(或來自返回整數的函數),當結果大於9223372036854775807時,會得到意想不到的結果。
· FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
小(單精度)浮點數。允許的值是-3.402823466E+38到-1.175494351E-38、0和1.175494351E-38到3.402823466E+38。這些是理論限制,基於IEEE標準。實際的範圍根據硬件或操作系統的不同可能稍微小些。
M是小數縱位數,D是小數點後面的位數。如果M和D被省略,根據硬件允許的限制來保存值。單精度浮點數精確到大約7位小數位。
如果指定UNSIGNED,不允許負值。
使用浮點數可能會遇到意想不到的問題,因爲在MySQL中的所有計算用雙精度完成。參見A.5.7節,“解決與不匹配行有關的問題”。
· DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
普通大小(雙精度)浮點數。允許的值是-1.7976931348623157E+308到-2.2250738585072014E-308、0和2.2250738585072014E-308到 1.7976931348623157E+308。這些是理論限制,基於IEEE標準。實際的範圍根據硬件或操作系統的不同可能稍微小些。
M是小數總位數,D是小數點後面的位數。如果M和D被省略,根據硬件允許的限制來保存值。雙精度浮點數精確到大約15位小數位。
如果指定UNSIGNED,不允許負值。
· DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED] [ZEROFILL]
爲DOUBLE的同義詞。除了:如果SQL服務器模式包括REAL_AS_FLOAT選項,REAL是FLOAT的同義詞而不是DOUBLE的同義詞。
· FLOAT(p) [UNSIGNED] [ZEROFILL]
浮點數。p表示精度(以位數表示),但MySQL只使用該值來確定是否結果列的數據類型爲FLOAT或DOUBLE。如果p爲從0到24,數據類型變爲沒有M或D值的FLOAT。如果p爲從25到53,數據類型變爲沒有M或D值的DOUBLE。結果列範圍與本節前面描述的單精度FLOAT或雙精度DOUBLE數據類型相同。
FLOAT(p)語法與ODBC兼容。
· DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]
壓縮的“嚴格”定點數。M是小數位數(精度)的總數,D是小數點(標度)後面的位數。小數點和(負數)的‘-’符號不包括在M中。如果D是0,則值沒有小數點或分數部分。DECIMAL整數最大位數(M)爲65。支持的十進制數的最大位數(D)是30。如果D被省略, 默認是0。如果M被省略, 默認是10。
如果指定UNSIGNED,不允許負值。
所有DECIMAL列的基本計算(+,-,*,/)用65位精度完成。
· DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]
是DECIMAL的同義詞。FIXED同義詞適用於與其它服務器的兼容性。
本節綜合討論了臨時列類型。詳細信息,參見11.3節,“日期和時間類型”。列存儲需求參見11.5節,“列類型存儲需求”。
· DATE
日期。支持的範圍爲'1000-01-01'到'9999-12-31'。MySQL以'YYYY-MM-DD'格式顯示DATE值,但允許使用字符串或數字爲DATE列分配值。
· DATETIME
日期和時間的組合。支持的範圍是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。MySQL以'YYYY-MM-DD HH:MM:SS'格式顯示DATETIME值,但允許使用字符串或數字爲DATETIME列分配值。
· TIMESTAMP[(M)]
時間戳。範圍是'1970-01-01 00:00:00'到2037年。
TIMESTAMP列用於INSERT或UPDATE操作時記錄日期和時間。如果你不分配一個值,表中的第一個TIMESTAMP列自動設置爲最近操作的日期和時間。也可以通過分配一個NULL值,將TIMESTAMP列設置爲當前的日期和時間。
TIMESTAMP值返回後顯示爲'YYYY-MM-DD HH:MM:SS'格式的字符串,顯示寬度固定爲19個字符。如果想要獲得數字值,應在TIMESTAMP 列添加+0。
註釋:MySQL 4.1以前使用的TIMESTAMP格式在MySQL 5.1中不支持;關於舊格式的信息參見MySQL 4.1 參考手冊。
· TIME
時間。範圍是'-838:59:59'到'838:59:59'。MySQL以'HH:MM:SS'格式顯示TIME值,但允許使用字符串或數字爲TIME列分配值。
· YEAR[(2|4)]
兩位或四位格式的年。默認是四位格式。在四位格式中,允許的值是1901到2155和0000。在兩位格式中,允許的值是70到69,表示從1970年到2069年。MySQL以YYYY 格式顯示YEAR值,但允許使用字符串或數字爲YEAR列分配值。
本節綜合討論了字符串列類型。詳細信息參見11.4節,“String類型”。列存儲需求參見11.5節,“列類型存儲需求”。
在某些情況中,MySQL可以將一個字符串列更改爲不同於CREATE TABLE或ALTER TABLE語句中所給出的類型。參見13.1.5.1節,“沉寂的列規格變更”。
MySQL 5.1字符串數據類型包括部分在MySQL 4.1之前的版本中沒有的特性:
· 許多字符串數據類型的列定義可以包括指定字符集的CHARACTER SET屬性,也可能包括校對規則。(CHARSET是CHARACTER SET的一個同義詞)。這些屬性適用於CHAR、VARCHAR、TEXT類型、ENUM和SET。例如:
· CREATE TABLE t
· (
· c1 CHAR(20) CHARACTER SET utf8,
· c2 CHAR(20) CHARACTER SET latin1 COLLATE latin1_bin
· );
該表定義創建了一個名爲c1的列,具有一個utf8字符集和該字符集的默認 校對規則,和一個名爲c2的列以及latin1字符集和該字符集的二元 校對規則。二元校對規則對大小寫不敏感。
· MySQL 5.1用字符單位解釋在字符列定義中的長度規範。(以前的一些MySQL版本以字節解釋長度)。
· 對於CHAR、VARCHAR和TEXT類型,BINARY屬性可以爲列分配該列字符集的 校對規則。
· 字符列的排序和比較基於分配給列的字符集。在以前的版本中,排序和比較基於服務器字符集的校對規則。對於CHAR和VARCHAR 列,你可以用BINARY屬性聲明列讓排序和 校對規則使用當前的字符代碼值而不是詞彙順序。
關於MySQL 5.1中字符集的支持,參見第10章:字符集支持。
· [NATIONAL] CHAR(M) [BINARY| ASCII | UNICODE]
固定長度字符串,當保存時在右側填充空格以達到指定的長度。M表示列長度。M的範圍是0到255個字符。
註釋:當檢索CHAR值時尾部空格被刪除。
如果想要將某個CHAR的長度設爲大於255,執行的CREATE TABLE或ALTER TABLE語句將失敗並提示錯誤:
mysql> CREATE TABLE c1 (col1 INT, col2 CHAR(500));
ERROR 1074 (42000): Column length too big for column 'col' (max = 255); use BLOB or TEXT instead
mysql> SHOW CREATE TABLE c1;
ERROR 1146 (42S02): Table 'test.c1' doesn't exist
CHAR是CHARACTER的簡寫。NATIONAL CHAR(或其等效短形式NCHAR)是標準的定義CHAR列應使用 默認字符集的SQL方法。這在MySQL中爲默認值。
BINARY屬性是指定列字符集的二元 校對規則的簡寫。排序和比較基於數值字符值。
列類型CHAR BYTE是CHAR BINARY的一個別名。這是爲了保證兼容性。
可以爲CHAR指定ASCII屬性。它分配latin1字符集。
可以爲CHAR指定UNICODE屬性。它分配ucs2字符集。
MySQL允許創建類型CHAR(0)的列。這主要用於必須有一個列但實際上不使用值的舊版本的應用程序相兼容。當你需要只能取兩個值的列時也很好:沒有定義爲NOT NULL的一個CHAR(0)列只佔用一位,只可以取值NULL和''(空字符串)。
· CHAR
這是CHAR(1)的同義詞。
· [NATIONAL] VARCHAR(M) [BINARY]
變長字符串。M 表示最大列長度。M的範圍是0到65,535。(VARCHAR的最大實際長度由最長的行的大小和使用的字符集確定。最大有效長度是65,532字節)。
註釋:MySQL 5.1遵從標準SQL規範,並且不刪除VARCHAR值的尾部空格。
VARCHAR是字符VARYING的簡寫。
BINARY屬性是指定列的字符集的二元 校對規則的簡寫。排序和比較基於數值字符值。
VARCHAR保存時用一個字節或兩個字節長的前綴+數據。如果VARCHAR列聲明的長度大於255,長度前綴是兩個字節。
· BINARY(M)
BINARY類型類似於CHAR類型,但保存二進制字節字符串而不是非二進制字符串。
· VARBINARY(M)
VARBINARY類型類似於VARCHAR類型,但保存二進制字節字符串而不是非二進制字符串。
· TINYBLOB
最大長度爲255(28–1)字節的BLOB列。
· TINYTEXT
最大長度爲255(28–1)字符的TEXT列。
· BLOB[(M)]
最大長度爲65,535(216–1)字節的BLOB列。
可以給出該類型的可選長度M。如果給出,則MySQL將列創建爲最小的但足以容納M字節長的值的BLOB類型。
· TEXT[(M)]
最大長度爲65,535(216–1)字符的TEXT列。
可以給出可選長度M。則MySQL將列創建爲最小的但足以容納M字符長的值的TEXT類型。
· MEDIUMBLOB
最大長度爲16,777,215(224–1)字節的BLOB列。
· MEDIUMTEXT
最大長度爲16,777,215(224–1)字符的TEXT列。
· LONGBLOB
最大長度爲4,294,967,295或4GB(232–1)字節的BLOB列。LONGBLOB列的最大有效(允許的)長度取決於客戶端/服務器協議中配置最大包大小和可用的內存。
· LONGTEXT
最大長度爲4,294,967,295或4GB(232–1)字符的TEXT列。LONGTEXT列的最大有效(允許的)長度取決於客戶端/服務器協議中配置最大包大小和可用的內存。
· ENUM('value1','value2',...)
枚舉類型。只能有一個值的字符串,從值列'value1','value2',...,NULL中或特殊 ''錯誤值中選出。ENUM列最多可以有65,535個截然不同的值。ENUM值在內部用整數表示。
· SET('value1','value2',...)
一個設置。字符串對象可以有零個或多個值,每個值必須來自列值'value1','value2',...SET列最多可以有64個成員。SET值在內部用整數表示。
MySQL支持所有標準SQL數值數據類型。這些類型包括嚴格數值數據類型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似數值數據類型(FLOAT、REAL和DOUBLE PRECISION)。關鍵字INT是INTEGER的同義詞,關鍵字DEC是DECIMAL的同義詞。
BIT數據類型保存位字段值,並且支持MyISAM、MEMORY、InnoDB和BDB表。
作爲SQL標準的擴展,MySQL也支持整數類型TINYINT、MEDIUMINT和BIGINT。下面的表顯示了需要的每個整數類型的存儲和範圍。
類型 |
字節 |
最小值 |
最大值 |
|
|
(帶符號的/無符號的) |
(帶符號的/無符號的) |
TINYINT |
1 |
-128 |
127 |
|
|
0 |
255 |
SMALLINT |
2 |
-32768 |
32767 |
|
|
0 |
65535 |
MEDIUMINT |
3 |
-8388608 |
8388607 |
|
|
0 |
16777215 |
INT |
4 |
-2147483648 |
2147483647 |
|
|
0 |
4294967295 |
BIGINT |
8 |
-9223372036854775808 |
9223372036854775807 |
|
|
0 |
18446744073709551615 |
MySQL還支持選擇在該類型關鍵字後面的括號內指定整數值的顯示寬度(例如,INT(4))。該可選顯示寬度規定用於顯示寬度小於指定的列寬度的值時從左側填滿寬度。
顯示寬度並不限制可以在列內保存的值的範圍,也不限制超過列的指定寬度的值的顯示。
當結合可選擴展屬性ZEROFILL使用時, 默認補充的空格用零代替。例如,對於聲明爲INT(5) ZEROFILL的列,值4檢索爲00004。請注意如果在整數列保存超過顯示寬度的一個值,當MySQL爲複雜聯接生成臨時表時會遇到問題,因爲在這些情況下MySQL相信數據適合原列寬度。
所有整數類型可以有一個可選(非標準)屬性UNSIGNED。當你想要在列內只允許非負數和該列需要較大的上限數值範圍時可以使用無符號值。
浮點和定點類型也可以爲UNSIGNED。同數類型,該屬性防止負值保存到列中。然而,與整數類型不同的是,列值的上範圍保持不變。
如果爲一個數值列指定ZEROFILL,MySQL自動爲該列添加UNSIGNED屬性。
對於浮點列類型,在MySQL中單精度值使用4個字節,雙精度值使用8個字節。
FLOAT類型用於表示近似數值數據類型。SQL標準允許在關鍵字FLOAT後面的括號內選擇用位指定精度(但不能爲指數範圍)。MySQL還支持可選的只用於確定存儲大小的精度規定。0到23的精度對應FLOAT列的4字節單精度。24到53的精度對應DOUBLE列的8字節雙精度。
MySQL允許使用非標準語法:FLOAT(M,D)或REAL(M,D)或DOUBLE PRECISION(M,D)。這裏,“(M,D)”表示該值一共顯示M位整數,其中D位位於小數點後面。例如,定義爲FLOAT(7,4)的一個列可以顯示爲-999.9999。MySQL保存值時進行四捨五入,因此如果在FLOAT(7,4)列內插入999.00009,近似結果是999.0001。
MySQL將DOUBLE視爲DOUBLE PRECISION(非標準擴展)的同義詞。MySQL還將REAL視爲DOUBLE PRECISION(非標準擴展)的同義詞,除非SQL服務器模式包括REAL_AS_FLOAT選項。
爲了保證最大可能的可移植性,需要使用近似數值數據值存儲的代碼應使用FLOAT或DOUBLE PRECISION,不規定精度或位數。
DECIMAL和NUMERIC類型在MySQL中視爲相同的類型。它們用於保存必須爲確切精度的值,例如貨幣數據。當聲明該類型的列時,可以(並且通常要)指定精度和標度;例如:
salary DECIMAL(5,2)
在該例子中,5是精度,2是標度。精度表示保存值的主要位數,標度表示小數點後面可以保存的位數。
在MySQL 5.1中以二進制格式保存DECIMAL和NUMERIC值。
標準SQL要求salary列能夠用5位整數位和兩位小數保存任何值。因此,在這種情況下可以保存在salary列的值的範圍是從-999.99到999.99。
在標準SQL中,語法DECIMAL(M)等價於DECIMAL(M,0)。同樣,語法DECIMAL等價於DECIMAL(M,0),可以通過計算確定M的值。在MySQL 5.1中支持DECIMAL和NUMERIC數據類型的變量形式。M默認值是10。
DECIMAL或NUMERIC的最大位數是65,但具體的DECIMAL或NUMERIC列的實際範圍受具體列的精度或標度約束。如果此類列分配的值小數點後面的位數超過指定的標度允許的範圍,值被轉換爲該標度。(具體操作與操作系統有關,但一般結果均被截取到允許的位數)。
BIT數據類型可用來保存位字段值。BIT(M)類型允許存儲M位值。M範圍爲1到64。
要指定位值,可以使用b'value'符。value是一個用0和1編寫的二進制值。例如,b'111'和b'100000000'分別表示7和128。參見9.1.5節,“位字段值”。
如果爲BIT(M)列分配的值的長度小於M位,在值的左邊用0填充。例如,爲BIT(6)列分配一個值b'101',其效果與分配b'000101'相同。
當要在一個數值列內保存一個超出該列允許範圍的值時,MySQL的操作取決於此時有效的SQL模式。如果模式未設置,MySQL將值裁剪到範圍的相應端點,並保存裁減好的值。但是,如果模式設置爲traditional(“嚴格模式”),超出範圍的值將被拒絕並提示錯誤,並且根據SQL標準插入會失敗。參見5.3.2節,“SQL服務器模式”。
如果INT列是UNSIGNED,列範圍的大小相同,但其端點會變爲到0和4294967295。如果你試圖保存-9999999999和9999999999,以非嚴格模式保存到列中的值是0和4294967296。
如果在浮點或定點列中分配的值超過指定(或默認)精度和標度規定的範圍,MySQL以非嚴格模式保存表示範圍相應端點的值。
當MySQL沒有工作在嚴格模式時,對於ALTER TABLE、LOAD DATA INFILE、UPDATE和多行INSERT語句,由於裁剪髮生的轉換將報告爲警告。當MySQL工作在嚴格模式時,這些語句將失敗,並且部分或全部值不會插入或更改,取決於是否表爲事務表和其它因素。詳情參見5.3.2節,“SQL服務器模式”。
表示時間值的DATE和時間類型爲DATETIME、DATE、TIMESTAMP、TIME和YEAR。每個時間類型有一個有效值範圍和一個“零”值,當指定不合法的MySQL不能表示的值時使用“零”值。TIMESTAMP類型有專有的自動更新特性,將在後面描述。
如果試圖插入一個不合法的日期,MySQL將給出警告或錯誤。可以使用ALLOW_INVALID_DATES SQL模式讓MySQL接受某些日期,例如'1999-11-31'。當你想要保存一個“可能錯誤的”用戶已經在數據庫中指定(例如,以web形式)用於將來處理的值時很有用。在這種模式下,MySQL只驗證月範圍爲從0到12,日範圍爲從0到31。這些範圍可以包括零,因爲MySQL允許在DATE或DATETIME列保存日/月和日是零的日期。這在應用程序需要保存一個你不知道確切日期的生日時非常有用。在這種情況下,只需要將日期保存爲'1999-00-00'或'1999-01-00'。如果保存此類日期,DATE_SUB()或DATE_ADD等需要完整日期的函數不會得到正確的結果。(如果你不想在日期中出現零,可以使用NO_ZERO_IN_DATE SQL模式)。
MySQL還允許將'0000-00-00'保存爲“僞日期”(如果不使用NO_ZERO_DATE SQL模式)。這在某些情況下比使用NULL值更方便(並且數據和索引佔用的空間更小)。
將sql_mode系統變量設置爲相應模式值,可以更確切你想讓MySQL支持哪種日期。參見5.3.2節,“SQL服務器模式”。
當使用日期和時間類型時應記住以下幾點:
· MySQL以標準輸出格式檢索給定日期或時間類型的值,但它盡力解釋你指定的各種輸入值格式(例如,當你指定一個分配給或與日期或時間類型進行比較的值時)。只支持下面章節中描述的格式。期望你能提供有效值。如果你使用其它格式的值會發生意想不到的結果。
· 包含兩位年值的日期會令人模糊,因爲世紀不知道。MySQL使用以下規則解釋兩位年值:
o 70-99範圍的年值轉換爲1970-1999。
o 00-69範圍的年值轉換爲2000-2069。
· 儘管MySQL嘗試解釋幾種格式的值,日期總是以年-月-日順序(例如,'98-09-04'),而不是其它地方常用的月-日-年或日-月-年順序(例如,'09-04-98','04-09-98')。
· 如果值用於數值上下文中,MySQL自動將日期或時間類型的值轉換爲數字,反之亦然。
· 當 MySQL遇到一個日期或時間類型的超出範圍或對於該類型不合法的值時(如本節開始所描述),它將該值轉換爲該類的“零”值。一個例外是超出範圍的TIME值被裁剪到TIME範圍的相應端點。
下面的表顯示了各類“零”值的格式。請注意如果啓用NO_ZERO_DATE SQL模式,使用這些值會產生警告。
列類型 |
“零”值 |
DATETIME |
'0000-00-00 00:00:00' |
DATE |
'0000-00-00' |
TIMESTAMP |
00000000000000 |
TIME |
'00:00:00' |
YEAR |
0000 |
· “零”值是特殊值,但你可以使用表內顯示的值顯式保存或引用它們。你也可以使用值'0'或0來保存或引用,寫起來更容易。
· MyODBC中使用的“零”日期或時間值在MyODBC 2.50.12和以上版本中被自動轉換爲NULL,因爲ODBC不能處理此類值。
DATETIME、DATE和TIMESTAMP類型是相關的。該節描述了它們的特徵,它們的相似點和不同點。
當你需要同時包含日期和時間信息的值時則使用DATETIME類型。MySQL以'YYYY-MM-DD HH:MM:SS'格式檢索和顯示DATETIME值。支持的範圍爲'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。(“支持”表示儘管先前的值可能工作,但沒有保證)。
當你只需要日期值而不需要時間部分時應使用DATE類型。MySQL用'YYYY-MM-DD'格式檢索和顯示DATE值。支持的範圍是'1000-01-01'到 '9999-12-31'。
TIMESTAMP列類型的屬性不固定,取決於MySQL版本和服務器運行的SQL模式。這些屬性將在本節後面描述。
可以使用任何常見格式指定DATETIME、DATE和TIMESTAMP值:
· 'YYYY-MM-DD HH:MM:SS'或'YY-MM-DD HH:MM:SS'格式的字符串。允許“不嚴格”語法:任何標點符都可以用做日期部分或時間部分之間的間割符。例如,'98-12-31 11:30:45'、'98.12.31 11+30+45'、'98/12/31 11*30*45'和'98@12@31 11^30^45'是等價的。
· 'YYYY-MM-DD'或'YY-MM-DD'格式的字符串。這裏也允許使用“不嚴格的”語法。例如,'98-12-31'、'98.12.31'、'98/12/31'和'98@12@31'是等價的。
· 'YYYYMMDDHHMMSS'或'YYMMDDHHMMSS'格式的沒有間割符的字符串,假定字符串對於日期類型是有意義的。例如,'19970523091528'和'970523091528'被解釋爲'1997-05-23 09:15:28',但'971122129015'是不合法的(它有一個沒有意義的分鐘部分),將變爲'0000-00-00 00:00:00'。
· 'YYYYMMDD'或'YYMMDD'格式的沒有間割符的字符串,假定字符串對於日期類型是有意義的。例如,'19970523'和'970523'被解釋爲 '1997-05-23',但'971332'是不合法的(它有一個沒有意義的月和日部分),將變爲'0000-00-00'。
· YYYYMMDDHHMMSS或YYMMDDHHMMSS格式的數字,假定數字對於日期類型是有意義的。例如,19830905132800和830905132800被解釋爲 '1983-09-05 13:28:00'。
· YYYYMMDD或YYMMDD格式的數字,假定數字對於日期類型是有意義的。例如,19830905和830905被解釋爲'1983-09-05'。
· 函數返回的結果,其值適合DATETIME、DATE或者TIMESTAMP上下文,例如NOW()或CURRENT_DATE。
無效DATETIME、DATE或者TIMESTAMP值被轉換爲相應類型的“零”值('0000-00-00 00:00:00'、'0000-00-00'或者00000000000000)。
對於包括日期部分間割符的字符串值,如果日和月的值小於10,不需要指定兩位數。'1979-6-9'與'1979-06-09'是相同的。同樣,對於包括時間部分間割符的字符串值,如果時、分和秒的值小於10,不需要指定兩位數。'1979-10-30 1:2:3'與'1979-10-30 01:02:03'相同。
數字值應爲6、8、12或者14位長。如果一個數值是8或14位長,則假定爲YYYYMMDD或YYYYMMDDHHMMSS格式,前4位數表示年。如果數字 是6或12位長,則假定爲YYMMDD或YYMMDDHHMMSS格式,前2位數表示年。其它數字被解釋爲彷彿用零填充到了最近的長度。
指定爲非限定符字符串的值使用給定的長度進行解釋。如果字符串爲8或14字符長,前4位數表示年。否則,前2位數表示年。從左向右解釋字符串內出現的各部分,以發現年、月、日、小時、分和秒值。這說明不應使用少於6字符的字符串。例如,如果你指定'9903',認爲它表示1999年3月,MySQL將在你的表內插入一個“零”日期值。這是因爲年和月值是99和03,但日部分完全丟失,因此該值不是一個合法的日期。但是,可以明顯指定一個零值來代表缺少的月或日部分。例如,可以使用'990300'來插入值'1999-03-00'。
在一定程度上,可以將一個日期類型的值分配給一個不同的日期類型。但是,值可能會更改或丟失一些信息:
· 如果你爲一個DATETIME或TIMESTAMP對象分配一個DATE值,結果值的時間部分被設置爲'00:00:00',因爲DATE值未包含時間信息。
· 如果你爲一個DATE對象分配一個DATETIME或TIMESTAMP值,結果值的時間部分被刪除,因爲DATE值未包含時間信息。
· 記住儘管可以使用相同的格式指定DATETIME、DATE和TIMESTAMP值,不同類型的值的範圍卻不同。例如,TIMESTAMP值不能早於1970或晚於2037。這說明一個日期,例如'1968-01-01',雖然對於DATETIME或DATE值是有效的,但對於TIMESTAMP值卻無效,如果分配給這樣一個對象將被轉換爲0。
當指定日期值時請注意某些缺陷:
· 指定爲字符串的值允許的非嚴格格式可能會欺騙。例如,值'10:11:12'由於‘:’間割符看上去可能象時間值,但如果用於日期上下文值則被解釋爲年'2010-11-12'。值'10:45:15'被轉換爲'0000-00-00'因爲'45'不是合法月。
· 在非嚴格模式,MySQL服務器只對日期的合法性進行基本檢查:年、月和日的範圍分別是1000到9999、00到12和00到31。任何包含超出這些範圍的部分的日期被轉換成'0000-00-00'。請注意仍然允許你保存非法日期,例如'2002-04-31'。要想確保不使用嚴格模式時日期有效,應檢查應用程序。
在嚴格模式,非法日期不被接受,並且不轉換。
詳細信息參見5.3.2節,“SQL服務器模式”。
· 包含兩位年值的日期會令人模糊,因爲世紀不知道。MySQL使用以下規則解釋兩位年值:
o 00-69範圍的年值轉換爲2000-2069。
o 70-99範圍的年值轉換爲1970-1999。
註釋:在舊版本的MySQL中(4.1之前),TIMESTAMP列類型的屬性在許多方面於本節所描述的大大不同。如果你需要對舊的TIMESTAMP數據進行轉化以便在MySQL 5.1中工作,詳情請參見MySQL 4.1 參考手冊。
TIMESTAMP列的顯示格式與DATETIME列相同。換句話說,顯示寬度固定在19字符,並且格式爲YYYY-MM-DD HH:MM:SS。
MySQL服務器也可以以MAXDB模式運行。當服務器以該模式運行時,TIMESTAMP與DATETIME相等。也就是說,如果創建表時服務器以MAXDB模式運行,TIMESTAMP列創建爲DATETIME列。結果是,該列使用DATETIME顯示格式,有相同的值範圍,並且沒有自動對當前的日期和時間進行初始化或更新。
要想啓用MAXDB模式,在啓動服務器時使用--sql-mode=MAXDB服務器選項或在運行時通過設置全局sql_mode變量將SQL服務器模式設置爲MAXDB:
mysql> SET GLOBAL sql_mode=MAXDB;
客戶端可以按照下面方法讓服務器爲它的連接以MAXDB模式運行:
mysql> SET SESSION sql_mode=MAXDB;
MySQL不接受在日或月列包括一個零或包含非法日期值的時間戳值。該規則的唯一例外是特殊值'0000-00-00 00:00:00'。
你可以非常靈便地確定什麼時候初始化和更新TIMESTAMP和對哪些列進行初始化和更新:
· 你可以將當前的時間戳指定爲默認值和自動更新的值。但只能選擇一個,或者兩者都不選。(不可能一個列選擇一個行爲而另一個列選擇另一個行爲)。
· 你可以指定哪個TIMESTAMP列自動初始化或更新爲當前的日期和時間。不再需要爲第1個TIMESTAMP列。
請注意下面討論所信息只適用於創建時未啓用MAXDB模式的表的TIMESTAMP列。(如上所述,MAXDB模式使列創建爲DATETIME列)。控制TIMESTAMP列的初始化和更新的規則如下所示:
· 如果一個表內的第1個TIMESTAMP列指定爲一個DEFAULT值,則不能忽略。 默認值可以爲CURRENT_TIMESTAMP或常量日期和時間值。
· DEFAULT NULL與第1個TIMESTAMP 列的DEFAULT CURRENT_TIMESTAMP相同。對於其它TIMESTAMP列,DEFAULT NULL被視爲DEFAULT 0。
· 表內的任何一個TIMESTAMP列可以設置爲自動初始化爲當前時間戳和/或更新。
· 在CREATE TABLE語句中,可以用下面的任何一種方式聲明第1個TIMESTAMP列:
o 用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP子句,列爲默認值使用當前的時間戳,並且自動更新。
o 不使用DEFAULT或ON UPDATE子句,與DEFAULT CURRENT_TIMESTAMP ON UPDATECURRENT_TIMESTAMP相同。
o 用DEFAULT CURRENT_TIMESTAMP子句不用ON UPDATE子句,列爲默認值使用當前的時間戳但是不自動更新。
o 不用DEFAULT子句但用ON UPDATE CURRENT_TIMESTAMP子句,列有默認值0並自動更新。
o 用常量DEFAULT值,列有給出的 默認值。如果列有一個ON UPDATE CURRENT_TIMESTAMP子句,它自動更新,否則不。
換句話說,你可以爲初始值和自動更新的值使用當前的時間戳,或者其中一個使用,或者兩個皆不使用。(例如,你可以指定ON UPDATE來啓用自動更新而不讓列自動初始化)。
· 在DEFAULT和ON UPDATE子句中可以使用CURRENT_TIMESTAMP、CURRENT_TIMESTAMP()或者NOW()。它們均具有相同的效果。
兩個屬性的順序並不重要。如果一個TIMESTAMP列同時指定了DEFAULT和ON UPDATE,任何一個可以在另一個的前面。
例子,下面這些語句是等效的:
CREATE TABLE t (ts TIMESTAMP);
CREATE TABLE t (ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE t (ts TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
DEFAULT CURRENT_TIMESTAMP);
· 要爲TIMESTAMP列而不是第1列指定自動默認或更新,必須通過將第1個TIMESTAMP列顯式分配一個常量DEFAULT值來禁用自動初始化和更新。(例如,DEFAULT 0或DEFAULT'2003-01-01 00:00:00')。然後,對於其它TIMESTAMP列,規則與第1個TIMESTAMP列相同,例外情況是不能忽略DEFAULT和ON UPDATE子句。如果這樣做,則不會自動進行初始化或更新。
例如:下面這些語句是等效的:
CREATE TABLE t (
ts1 TIMESTAMP DEFAULT 0,
ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE t (
ts1 TIMESTAMP DEFAULT 0,
ts2 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
DEFAULT CURRENT_TIMESTAMP);
可以對每個連接設置當前的時區,相關描述參見5.10.8節,“MySQL服務器時區支持”。TIMESTAMP值以UTC格式保存,存儲時對當前的時區進行轉換,檢索時再轉換回當前的時區。只要時區設定值爲常量,便可以得到保存時的值。如果保存一個TIMESTAMP值,應更改時區然後檢索該值,它與你保存的值不同。這是因爲在兩個方向的轉換中沒有使用相同的時區。當前的時區可以用作time_zone系統變量的值。
可以在TIMESTAMP列的定義中包括NULL屬性以允許列包含NULL值。例如:
CREATE TABLE t
(
ts1 TIMESTAMP NULL DEFAULT NULL,
ts2 TIMESTAMP NULL DEFAULT 0,
ts3 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP
);
如果未指定NULL屬性,將列設置爲NULL設置則會將它設置爲當前的時間戳。請注意允許NULL值的TIMESTAMP列不會採用當前的時間戳,除非要麼其 默認值定義爲CURRENT_TIMESTAMP,或者NOW()或CURRENT_TIMESTAMP被插入到該列內。換句話說,只有使用如下定義創建,定義爲 NULL的TIMESTAMP列纔會自動更新:
CREATE TABLE t (ts NULLDEFAULT CURRENT_TIMESTAMP);
否則-也就是說,如果使用NULL而不是DEFAULT TIMESTAMP來定義TIMESTAMP列,如下所示...
CREATE TABLE t1 (ts NULL DEFAULT NULL);
CREATE TABLE t2 (ts NULL DEFAULT '0000-00-00 00:00:00');
...則必須顯式插入一個對應當前日期和時間的值。例如:
INSERT INTO t1 VALUES (NOW());
INSERT INTO t2 VALUES (CURRENT_TIMESTAMP);
MySQL以'HH:MM:SS'格式檢索和顯示TIME值(或對於大的小時值採用'HHH:MM:SS'格式)。TIME值的範圍可以從'-838:59:59'到'838:59:59'。小時部分會因此大的原因是TIME類型不僅可以用於表示一天的時間(必須小於24小時),還可能爲某個事件過去的時間或兩個事件之間的時間間隔(可以大於24小時,或者甚至爲負)。
你可以用各種格式指定TIME值:
· 'D HH:MM:SS.fraction'格式的字符串。還可以使用下面任何一種“非嚴格”語法:'HH:MM:SS.fraction'、'HH:MM:SS'、'HH:MM'、'D HH:MM:SS'、'D HH:MM'、'D HH'或'SS'。這裏D表示日,可以取0到34之間的值。請注意MySQL還不保存分數。
· 'HHMMSS'格式的沒有間割符的字符串,假定是有意義的時間。例如,'101112'被理解爲'10:11:12',但'109712'是不合法的(它有一個沒有意義的分鐘部分),將變爲'00:00:00'。
· HHMMSS格式的數值,假定是有意義的時間。例如,101112被理解爲'10:11:12'。下面格式也可以理解:SS、MMSS、HHMMSS、HHMMSS.fraction。請注意MySQL還不保存分數。
· 函數返回的結果,其值適合TIME上下文,例如CURRENT_TIME。
對於指定爲包括時間部分間割符的字符串的TIME值,如果時、分或者秒值小於10,則不需要指定兩位數。'8:3:2'與'08:03:02'相同。
爲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'。
超出TIME範圍但合法的值被裁爲範圍最接近的端點。例如,'-850:00:00'和'850:00:00'被轉換爲'-838:59:59'和'838:59:59'。
無效TIME值被轉換爲'00:00:00'。請注意由於'00:00:00'本身是一個合法TIME值,只從表內保存的一個'00:00:00'值還不能說出原來的值是 '00:00:00'還是不合法的值。
11.3.3. YEAR類型
YEAR類型是一個單字節類型用於表示年。
MySQL以YYYY格式檢索和顯示YEAR值。範圍是1901到2155。
可以指定各種格式的YEAR值:
· 四位字符串,範圍爲'1901'到'2155'。
· 四位數字,範圍爲1901到2155。
· 兩位字符串,範圍爲'00'到'99'。'00'到'69'和'70'到'99'範圍的值被轉換爲2000到2069和1970到1999範圍的YEAR值。
· 兩位整數,範圍爲1到99。1到69和70到99範圍的值被轉換爲2001到2069和1970到1999範圍的YEAR值。請注意兩位整數範圍與兩位字符串範圍稍有不同,因爲你不能直接將零指定爲數字並將它解釋爲2000。你必須將它指定爲一個字符串'0'或'00'或它被解釋爲0000。
· 函數返回的結果,其值適合YEAR上下文,例如NOW()。
非法YEAR值被轉換爲0000。
11.3.4. Y2K事宜和日期類型
MySQL本身對於2000年(Y2K)是安全的(參見1.4.5節,“2000年兼容性”),但輸入給MySQL的值可能不安全。任何包含兩位年值的輸入都會令人模糊,因爲世紀不知道。這些值必須解釋爲四位形式,因爲MySQL內部使用四位來保存年。
對於DATETIME、DATE、TIMESTAMP和YEAR類型,MySQL使用以下規則解釋含模糊年值的日期:
· 00-69範圍的年值轉換爲2000-2069。
· 70-99範圍的年值轉換爲1970-1999。
請記住這些規則只是合理猜測數據值表示什麼。如果MySQL使用的啓發不能產生正確的值,你應提供包含四位年值的確切輸入。
ORDER BY可以正確排序有兩位年的TIMESTAMP或YEAR值。
部分函數如MIN()和MAX()將TIMESTAMP或YEAR轉換爲一個數字。這說明使用有兩位年值的值,這些函數不能工作正確。在這種情況下的修復方法是將TIMESTAMP或YEAR轉換爲四位年格式或使用MIN(DATE_ADD(TIMESTAMP,INTERVAL 0 DAYS))。
CHAR和VARCHAR類型類似,但它們保存和檢索的方式不同。它們的最大長度和是否尾部空格被保留等方面也不同。在存儲或檢索過程中不進行大小寫轉換。
CHAR和VARCHAR類型聲明的長度表示你想要保存的最大字符數。例如,CHAR(30)可以佔用30個字符。
CHAR列的長度固定爲創建表時聲明的長度。長度可以爲從0到255的任何值。當保存CHAR值時,在它們的右邊填充空格以達到指定的長度。當檢索到CHAR值時,尾部的空格被刪除掉。在存儲或檢索過程中不進行大小寫轉換。
VARCHAR列中的值爲可變長字符串。長度可以指定爲0到65,535之間的值。(VARCHAR的最大有效長度由最大行大小和使用的字符集確定。整體最大長度是65,532字節)。
同CHAR對比,VARCHAR值保存時只保存需要的字符數,另加一個字節來記錄長度(如果列聲明的長度超過255,則使用兩個字節)。
VARCHAR值保存時不進行填充。當值保存和檢索時尾部的空格仍保留,符合標準SQL。
如果分配給CHAR或VARCHAR列的值超過列的最大長度,則對值進行裁剪以使其適合。如果被裁掉的字符不是空格,則會產生一條警告。如果裁剪非空格字符,則會造成錯誤(而不是警告)並通過使用嚴格SQL模式禁用值的插入。參見5.3.2節,“SQL服務器模式”。
下面的表顯示了將各種字符串值保存到CHAR(4)和VARCHAR(4)列後的結果,說明了CHAR和VARCHAR之間的差別:
值 |
CHAR(4) |
存儲需求 |
VARCHAR(4) |
存儲需求 |
'' |
' ' |
4個字節 |
'' |
1個字節 |
'ab' |
'ab ' |
4個字節 |
'ab ' |
3個字節 |
'abcd' |
'abcd' |
4個字節 |
'abcd' |
5個字節 |
'abcdefgh' |
'abcd' |
4個字節 |
'abcd' |
5個字節 |
請注意上表中最後一行的值只適用不使用嚴格模式時;如果MySQL運行在嚴格模式,超過列長度不的值不保存,並且會出現錯誤。
從CHAR(4)和VARCHAR(4)列檢索的值並不總是相同,因爲檢索時從CHAR列刪除了尾部的空格。通過下面的例子說明該差別:
mysql> CREATE TABLE vc (v VARCHAR(4), c CHAR(4));
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO vc VALUES ('ab ', 'ab ');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT CONCAT(v, '+'), CONCAT(c, '+') FROM vc;
+----------------+----------------+
| CONCAT(v, '+') | CONCAT(c, '+') |
+----------------+----------------+
| ab + | ab+ |
+----------------+----------------+
1 row in set (0.00 sec)
根據分配給列的字符集校對規則對CHAR和VARCHAR列中的值進行排序和比較。
請注意所有MySQL校對規則屬於PADSPACE類。這說明在MySQL中的所有CHAR和VARCHAR值比較時不需要考慮任何尾部空格。例如:
mysql> CREATE TABLE names (myname CHAR(10), yourname VARCHAR(10));
Query OK, 0 rows affected (0.09 sec)
mysql> INSERT INTO names VALUES ('Monty ', 'Monty ');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT myname = 'Monty ', yourname = 'Monty ' FROM names;
+--------------------+----------------------+
| myname = 'Monty ' | yourname = 'Monty ' |
+--------------------+----------------------+
| 1 | 1 |
+--------------------+----------------------+
1 row in set (0.00 sec)
請注意所有MySQL版本均如此,並且它不受SQL服務器模式的影響。
對於尾部填充字符被裁剪掉或比較時將它們忽視掉的情形,如果列的索引需要唯一的值,在列內插入一個只是填充字符數不同的值將會造成複製鍵值錯誤。
CHAR BYTE是CHAR BINARY的別名。這是爲了保證兼容性。
ASCII屬性爲CHAR列分配latin1字符集。UNICODE屬性分配ucs2字符集。
BINARY和VARBINARY類類似於CHAR和VARCHAR,不同的是它們包含二進制字符串而不要非二進制字符串。也就是說,它們包含字節字符串而不是字符字符串。這說明它們沒有字符集,並且排序和比較基於列值字節的數值值。
BINARY和VARBINARY允許的最大長度一樣,如同CHAR和VARCHAR,不同的是BINARY和VARBINARY的長度是字節長度而不是字符長度。
BINARY和VARBINARY數據類型不同於CHAR BINARY和VARCHAR BINARY數據類型。對於後一種類型,BINARY屬性不會將列視爲二進制字符串列。相反,它致使使用列字符集的二元 校對規則,並且列自身包含非二進制字符字符串而不是二進制字節字符串。例如CHAR(5) BINARY被視爲CHAR(5) CHARACTER SET latin1 COLLATE latin1_bin,假定默認字符集是latin1。這不同於BINARY(5),它保存5字節二進制字符串,沒有字符集或 校對規則。
當保存BINARY值時,在它們右邊填充值以達到指定長度。填充值是0x00(零字節)。插入值時在右側添加0x00 on,並且選擇時不刪除尾部的字節。比較時所有字節很重要,包括ORDER BY和DISTINCT操作。比較時0x00字節和空格是不同的,0x00<空格。
例如:對於一個BINARY(3)列,當插入時 'a' 變爲 'a \0'。'a\0'插入時變爲'a\0\0'。當選擇時兩個插入的值均不更改。
對於VARBINARY,插入時不填充字符,選擇時不裁剪字節。比較時所有字節很重要,包括ORDER BY和DISTINCT操作。比較時0x00字節和空格是不同的,0x00<空格。
對於尾部填充字符被裁剪掉或比較時將它們忽視掉的情形,如果列的索引需要唯一的值,在列內插入一個只是填充字符數不同的值將會造成複製鍵值錯誤。
如果你計劃使用這些數據類型來保存二進制數據並且需要檢索的值與保存的值完全相同,應考慮前面所述的填充和裁剪特徵。下面的例子說明了用0x00填充的BINARY值如何影響列值比較:
mysql> CREATE TABLE t (c BINARY(3));
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO t SET c = 'a';
Query OK, 1 row affected (0.01 sec)
mysql> SELECT HEX(c), c = 'a', c = 'a\0\0' from t;
+--------+---------+-------------+
| HEX(c) | c = 'a' | c = 'a\0\0' |
+--------+---------+-------------+
| 610000 | 0 | 1 |
+--------+---------+-------------+
1 row in set (0.09 sec)
如果檢索的值必須與指定進行存儲而沒有填充的值相同,最好使用BLOB數據類型。
創建表時,MySQL可以默默更改BINARY或VARBINARY列的類型。參見13.1.5.1節,“沉寂的列規格變更”。
BLOB是一個二進制大對象,可以容納可變數量的數據。有4種BLOB類型:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它們只是可容納值的最大長度不同。
有4種TEXT類型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。這些對應4種BLOB類型,有相同的最大長度和存儲需求。
BLOB 列被視爲二進制字符串(字節字符串)。TEXT列被視爲非二進制字符串(字符字符串)。BLOB列沒有字符集,並且排序和比較基於列值字節的數值值。TEXT列有一個字符集,並且根據字符集的 校對規則對值進行排序和比較。
在TEXT或BLOB列的存儲或檢索過程中,不存在大小寫轉換。
當未運行在嚴格模式時,如果你爲BLOB或TEXT列分配一個超過該列類型的最大長度的值值,值被截取以保證適合。如果截掉的字符不是空格,將會產生一條警告。使用嚴格SQL模式,會產生錯誤,並且值將被拒絕而不是截取並給出警告。參見5.3.2節,“SQL服務器模式”。
在大多數方面,可以將BLOB列視爲能夠足夠大的VARBINARY列。同樣,可以將TEXT列視爲VARCHAR列。BLOB和TEXT在以下幾個方面不同於VARBINARY和VARCHAR:
· 當保存或檢索BLOB和TEXT列的值時不刪除尾部空格。(這與VARBINARY和VARCHAR列相同)。
請注意比較時將用空格對TEXT進行擴充以適合比較的對象,正如CHAR和VARCHAR。
· 對於BLOB和TEXT列的索引,必須指定索引前綴的長度。對於CHAR和VARCHAR,前綴長度是可選的。參見7.4.3節,“列索引”。
· BLOB和TEXT列不能有 默認值。
LONG和LONG VARCHAR對應MEDIUMTEXT數據類型。這是爲了保證兼容性。如果TEXT列類型使用BINARY屬性,將爲列分配列字符集的二元 校對規則。
MySQL連接程序/ODBC將BLOB值定義爲LONGVARBINARY,將TEXT值定義爲LONGVARCHAR。
由於BLOB和TEXT值可能會非常長,使用它們時可能遇到一些約束:
· 當排序時只使用該列的前max_sort_length個字節。max_sort_length的 默認值是1024;該值可以在啓動mysqld服務器時使用--max_sort_length選項進行更改。參見5.3.3節,“服務器系統變量”。
運行時增加max_sort_length的值可以在排序或組合時使更多的字節有意義。任何客戶端可以更改其會話max_sort_length變量的值:
mysql> SET max_sort_length = 2000;
mysql> SELECT id, comment FROM tbl_name
-> ORDER BY comment;
當你想要使超過max_sort_length的字節有意義,對含長值的BLOB或TEXT列使用GROUP BY或ORDER BY的另一種方式是將列值轉換爲固定長度的對象。標準方法是使用SUBSTRING函數。例如,下面的語句對comment列的2000個字節進行排序:
mysql> SELECT id, SUBSTRING(comment,1,2000) FROM tbl_name
-> ORDER BY SUBSTRING(comment,1,2000);
· BLOB或TEXT對象的最大大小由其類型確定,但在客戶端和服務器之間實際可以傳遞的最大值由可用內存數量和通信緩存區大小確定。你可以通過更改max_allowed_packet變量的值更改消息緩存區的大小,但必須同時修改服務器和客戶端程序。例如,可以使用 mysql和mysqldump來更改客戶端的max_allowed_packet值。參見7.5.2節,“調節服務器參數”、8.3節,“mysql:MySQL命令行工具”和8.8節,“mysqldump:數據庫備份程序”。
每個BLOB或TEXT值分別由內部分配的對象表示。這與其它列類型形成對比,後者是當打開表時爲每1列分配存儲引擎。
ENUM是一個字符串對象,其值來自表創建時在列規定中顯式枚舉的一列值。
在某些情況下,ENUM值也可以爲空字符串('')或NULL:
· 如果你將一個非法值插入ENUM(也就是說,允許的值列之外的字符串),將插入空字符串以作爲特殊錯誤值。該字符串與“普通”空字符串不同,該字符串有數值值0。後面有詳細討論。
· 如果將ENUM列聲明爲允許NULL,NULL值則爲該列的一個有效值,並且 默認值爲NULL。如果ENUM列被聲明爲NOT NULL,其默認值爲允許的值列的第1個元素。
每個枚舉值有一個索引:
· 來自列規定的允許的值列中的值從1開始編號。
· 空字符串錯誤值的索引值是0。這說明你可以使用下面的SELECT語句來找出分配了非法ENUM值的行:
· mysql> SELECT * FROM tbl_name WHERE enum_col=0;
· NULL值的索引是NULL。
例如,定義爲ENUM的列('one','two','three')可以有下面所示任何值。還顯示了每個值的索引:
值 |
索引 |
NULL |
NULL |
'' |
0 |
'one' |
1 |
'two' |
2 |
'three' |
3 |
枚舉最多可以有65,535個元素。
當創建表時,ENUM成員值的尾部空格將自動被刪除。
當檢索時,保存在ENUM列的值使用列定義中所使用的大小寫來顯示。請注意可以爲ENUM列分配字符集和 校對規則。對於二進制或大小寫敏感的校對規則,當爲列分配值時應考慮大小寫。
如果在數值上下文中檢索一個ENUM值,將返回列值的索引。例如,你可以這樣從ENUM列搜索數值值:
mysql> SELECT enum_col+0 FROM tbl_name;
如果將一個數字保存到ENUM列,數字被視爲索引,並且保存的值是該索引對應的枚舉成員。(但是,這不適合LOAD DATA,它將所有輸入視爲字符串)。不建議使用類似數字的枚舉值來定義一個ENUM列,因爲這很容易引起混淆。例如,下面的列含有字符串值'0'、'1'和'2'的枚舉成員,但數值索引值爲1、2和3:
numbers ENUM('0','1','2')
根據枚舉成員在列定義中列出的順序對ENUM值進行排序。(換句話說,ENUM值根據索引編號進行排序)。例如,對於ENUM('a','b'),'a'排在'b'前面,但對於ENUM('b','a'),'b'排在'a'前面。空字符串排在非空字符串前面,並且NULL值排在所有其它枚舉值前面。要想防止意想不到的結果,按字母順序規定ENUM列。還可以使用GROUP BY CAST(col AS CHAR)或GROUP BY CONCAT(col)來確保按照詞彙對列進行排序而不是用索引數字。
如果你想要確定一個ENUM列的所有可能的值,使用SHOW COLUMNS FROM tbl_name LIKE enum_col,並解析輸出中第2列的ENUM定義。
11.4.5. SET類型
SET是一個字符串對象,可以有零或多個值,其值來自表創建時規定的允許的一列值。指定包括多個SET成員的SET列值時各成員之間用逗號(‘,’)間隔開。這樣SET成員值本身不能包含逗號。
例如,指定爲SET('one', 'two') NOT NULL的列可以有下面的任何值:
''
'one'
'two'
'one,two'
SET最多可以有64個不同的成員。
當創建表時,SET成員值的尾部空格將自動被刪除。
當檢索時,保存在SET列的值使用列定義中所使用的大小寫來顯示。請注意可以爲SET列分配字符集和 校對規則。對於二進制或大小寫敏感的校對規則,當爲列分配值時應考慮大小寫。
MySQL用數字保存SET值,所保存值的低階位對應第1個SET成員。如果在數值上下文中檢索一個SET值,檢索的值的位設置對應組成列值的SET成員。例如,你可以這樣從一個SET列檢索數值值:
mysql> SELECT set_col+0 FROM tbl_name;
如果將一個數字保存到SET列中,數字中二進制表示中的位確定了列值中的SET成員。對於指定爲SET('a','b','c','d')的列,成員有下面的十進制和二進制值:
SET成員 |
十進制值 |
二進制值 |
'a' |
1 |
0001 |
'b' |
2 |
0010 |
'c' |
4 |
0100 |
'd' |
8 |
1000 |
如果你爲該列分配一個值9,其二進制形式爲1001,因此第1個和第4個SET值成員'a'和'd'被選擇,結果值爲 'a,d'。
對於包含多個SET元素的值,當插入值時元素所列的順序並不重要。在值中一個給定的元素列了多少次也不重要。當以後檢索該值時,值中的每個元素出現一次,根據表創建時指定的順序列出元素。例如,假定某個列指定爲SET('a','b','c','d'):
mysql> CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));
插入值'a,d'、'd,a'、'a,d,d'、'a,d,a'和'd,a,d':
mysql> INSERT INTO myset (col) VALUES
-> ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
Query OK, 5 rows affected (0.01 sec)
Records: 5 Duplicates: 0 Warnings: 0
當檢索時所有這些值顯示爲 'a,d':
mysql> SELECT col FROM myset;
+------+
| col |
+------+
| a,d |
| a,d |
| a,d |
| a,d |
| a,d |
+------+
5 rows in set (0.04 sec)
如果將SET列設置爲一個不支持的值,則該值被忽略併發出警告:
mysql> INSERT INTO myset (col) VALUES ('a,d,d,s');
Query OK, 1 row affected, 1 warning (0.03 sec)
mysql> SHOW WARNINGS;
+---------+------+------------------------------------------+
| Level | Code | Message |
+---------+------+------------------------------------------+
| Warning | 1265 | Data truncated for column 'col' at row 1 |
+---------+------+------------------------------------------+
1 row in set (0.04 sec)
mysql> SELECT col FROM myset;
+------+
| col |
+------+
| a,d |
| a,d |
| a,d |
| a,d |
| a,d |
| a,d |
+------+
6 rows in set (0.01 sec)
SET值按數字順序排序。NULL值排在非NULL SET值的前面。
通常情況,可以使用FIND_IN_SET()函數或LIKE操作符搜索SET值:
mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;
mysql> SELECT * FROM tbl_name WHERE set_col LIKE '%value%';
第1個語句找出SET_col包含value set成員的行。第2個類似,但有所不同:它在其它地方找出set_col包含value的行,甚至是在另一個SET成員的子字符串中。
下面的語句也是合法的:
mysql> SELECT * FROM tbl_name WHERE set_col & 1;
mysql> SELECT * FROM tbl_name WHERE set_col = 'val1,val2';
第1個語句尋找包含第1個set成員的值。第2個語句尋找一個確切匹配的值。應注意第2類的比較。將set值與'val1,val2'比較返回的結果與同'val2,val1'比較返回的結果不同。指定值時的順序應與在列定義中所列的順序相同。
如果想要爲SET列確定所有可能的值,使用SHOW COLUMNS FROM tbl_name LIKE set_col並解析輸出中第2列的SET定義。
11.5. 列類型存儲需求
根據類別列出了MySQL支持的每個列類型的存儲需求。
MyISAM表中行的最大大小爲65,534字節。每個BLOB和TEXT列 賬戶只佔其中的5至9個字節。
如果MyISAM表包括變長列類型,記錄格式也是可變長度。當創建表時,在某些條件下,MySQL可以將一個列從變長類型改爲固定長度的類型或反之亦然。詳細信息參見13.1.5.1節,“沉寂的列規格變更”。
數值類型存儲需求
列類型 |
存儲需求 |
TINYINT |
1個字節 |
SMALLINT |
2個字節 |
MEDIUMINT |
3個字節 |
INT, INTEGER |
4個字節 |
BIGINT |
8個字節 |
FLOAT(p) |
如果0 <= p <= 24爲4個字節, 如果25 <= p <= 53爲8個字節 |
FLOAT |
4個字節 |
DOUBLE [PRECISION], item REAL |
8個字節 |
DECIMAL(M,D), NUMERIC(M,D) |
變長;參見下面的討論 |
BIT(M) |
大約(M+7)/8個字節 |
DECIMAL(和NUMERIC)的存儲需求與具體版本有關:
使用二進制格式將9個十進制(基於10)數壓縮爲4個字節來表示DECIMAL列值。每個值的整數和分數部分的存儲分別確定。每個9位數的倍數需要4個字節,並且“剩餘的”位需要4個字節的一部分。下表給出了超出位數的存儲需求:
剩餘的 |
字節 |
位數 |
數目 |
0 |
0 |
1 |
1 |
2 |
1 |
3 |
2 |
4 |
2 |
5 |
3 |
6 |
3 |
7 |
4 |
8 |
4 |
9 |
4 |
日期和時間類型的存儲需求
列類型 |
存儲需求 |
DATE |
3個字節 |
DATETIME |
8個字節 |
TIMESTAMP |
4個字節 |
TIME |
3個字節 |
YEAR |
1個字節 |
字符串類型的存儲需求
列類型 |
存儲需求 |
CHAR(M) |
M個字節,0 <= M <= 255 |
VARCHAR(M) |
L+1個字節,其中L <= M 且0 <= M <= 65535(參見下面的註釋) |
BINARY(M) |
M個字節,0 <= M <= 255 |
VARBINARY(M) |
L+1個字節,其中L <= M 且0 <= M <= 255 |
TINYBLOB, TINYTEXT |
L+1個字節,其中L < 28 |
BLOB, TEXT |
L+2個字節,其中L < 216 |
MEDIUMBLOB, MEDIUMTEXT |
L+3個字節,其中L < 224 |
LONGBLOB, LONGTEXT |
L+4個字節,其中L < 232 |
ENUM('value1','value2',...) |
1或2個字節,取決於枚舉值的個數(最多65,535個值) |
SET('value1','value2',...) |
1、2、3、4或者8個字節,取決於set成員的數目(最多64個成員) |
VARCHAR、BLOB和TEXT類是變長類型。每個類型的存儲需求取決於列值的實際長度(用前面的表中的L表示),而不是該類型的最大可能的大小。例如,VARCHAR(10)列可以容納最大長度爲10的字符串。實際存儲需求是字符串(L)的長度,加上一個記錄字符串長度的字節。對於字符串'abcd',L是4,存儲需要5個字節。
對於CHAR、VARCHAR和TEXT類型,前面的表中的值L和M應解釋爲字符數目,並且列定義中的這些類型的長度表示字符數目。例如,要想保存一個TINYTEXT值需要L字符+ 1個字節。
要想計算用於保存具體CHAR、VARCHAR或者TEXT列值的字節數,需要考慮該列使用的字符集。在具體情況中,當使用Unicode時,必須記住所有Unicode字符使用相同的字節數。爲了細分用於不同類Unicode字符使用的存儲,參見10.5節,“Unicode支持”。
註釋:VARCHAR列的有效最大長度爲65,532字符。
NDBCLUSTER引擎只支持固定寬度的列。這說明MySQL簇中的表中的VARCHAR列的行爲如同類型CHAR(不同的是每個記錄仍然有一個額外字節空間)。例如,在Cluster表中,聲明爲VARCHAR(100)的列中的每個記錄存儲時將佔用101個字節,無論實際存儲的記錄中的字符串的長度爲多少。
BLOB和TEXT類需要 1、2、3或者4個字節來記錄列值的長度,取決於該類的最大可能的長度。參見11.4.3節,“BLOB和TEXT類型”。
在NDB Cluster存儲引擎中,TEXT和BLOB列的實施是不同的,其中TEXT列中的每個記錄由兩個單獨部分組成。一個是固定大小(256字節),並且實際上保存在原表中。另一個包括超出256字節的任何數據,保存在隱含的表中。第2個表中的記錄總是2,000字節長。這說明如果size<= 256,TEXT列的大小爲256(其中size表示記錄的大小);否則,大小是256 +size+(2000–(size–256)%2000)。
ENUM對象的大小由不同的枚舉值的數目確定。枚舉用一個字節,可以有255個可能的值。當枚舉的值位於256和65,535之間時,用兩個字節。參見11.4.4節,“ENUM類型”。
SET對象的大小由不同的set成員的數量確定。如果set大小是N,對象佔(N+7)/8個字節,四捨五入到1、2、3、4或者8個字節。SET最多可以有64個成員。參見11.4.5節,“SET類型”。
爲了優化存儲,在任何情況下均應使用最精確的類型。例如,如果列的值的範圍爲從1到99999,若使用整數,則MEDIUMINT UNSIGNED是好的類型。在所有可以表示該列值的類型中,該類型使用的存儲最少。
用精度爲65位十進制數(基於10)對DECIMAL 列進行所有基本計算(+、-、*、/)。參見11.1.1節,“數值類型概述”。
使用雙精度操作對DECIMAL值進行計算。如果準確度不是太重要或如果速度爲最高優先級,DOUBLE類型即足夠了。爲了達到高精度,可以轉換到保存在BIGINT中的定點類型。這樣可以用64位整數進行所有計算,根據需要將結果轉換回浮點值。
爲了使用由其它賣方編寫的SQL執行代碼,MySQL按照下表所示對列類型進行映射。通過這些映射,可以很容易地從其它數據庫引擎將表定義導入到MySQL中:
其它賣方類型 |
MySQL類型 |
BOOL, |
TINYINT |
BOOLEAN |
TINYINT |
CHAR VARYING(M) |
VARCHAR(M) |
DEC |
DECIMAL |
FIXED |
DECIMAL |
FLOAT4 |
FLOAT |
FLOAT8 |
DOUBLE |
INT1 |
TINYINT |
INT2 |
SMALLINT |
INT3 |
MEDIUMINT |
INT4 |
INT |
INT8 |
BIGINT |
LONG VARBINARY |
MEDIUMBLOB |
LONG VARCHAR |
MEDIUMTEXT |
LONG |
MEDIUMTEXT |
MIDDLEINT |
MEDIUMINT |
NUMERIC |
DECIMAL |
在創建表時對列類型進行映射,然後原來的類型定義被丟棄。如果你使用其它賣方的類型創建一個表,然後執行DESCRIBE tbl_name語句,MySQL使用等效的MySQL類型來報告表的結構。例如:
mysql> CREATE TABLE t (a BOOL, b FLOAT8, c LONG, d NUMERIC);
Query OK, 0 rows affected (0.08 sec)
mysql> DESCRIBE t;
+-------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| a | tinyint(1) | YES | | NULL | |
| b | double | YES | | NULL | |
| c | mediumtext | YES | | NULL | |
| d | decimal(10,0) | YES | | NULL | |
+-------+---------------+------+-----+---------+-------+
4 rows in set (0.00 sec)