MySQL資料型別

cdrcsy發表於2024-09-10

MySQL 支援SQL資料型別的幾個類別:數字型別、日期和時間型別、字串(字元和位元組)型別、空間型別和 JSON資料型別。

==========================================資料型別 ==========================================

MySQL支援所有標準的SQL數值資料型別。這些型別包括精確的數值資料型別(INTEGER、SMALLINT、DECIMAL和numeric),以及近似的數值資料格式(FLOAT、REAL和DOUBLE PRECISION)。關鍵字INT是INTEGER的同義詞,關鍵字DEC和FIXED是DECIMAL的同義詞。MySQL將DOUBLE視為DOUBLE PRECISION(一種非標準擴充套件)的同義詞。MySQL還將REAL視為DOUBLE PRECISION(一種非標準變體)的同義詞,除非啟用了REAL_as_FLOAT SQL模式。資料型別BIT支援InnoDB、MyISAM、 MEMORY和NDB。

主要包括以下五大類:

整數型別:BIT、BOOL、TINY INT、SMALL INT、MEDIUM INT、 INT、 BIG INT
浮點數型別:FLOAT、DOUBLE、DECIMAL
字串型別:CHAR、VARCHAR、TINY TEXT、TEXT、MEDIUM TEXT、LONGTEXT、TINY BLOB、BLOB、MEDIUM BLOB、LONG BLOB
日期型別:Date、DateTime、TimeStamp、Time、Year
其他資料型別:BINARY、VARBINARY、ENUM、SET、Geometry、Point、MultiPoint、LineString、MultiLineString、Polygon、GeometryCollection等


1、數字型別:
對於整數資料型別,M 表示最小顯示寬度。最大顯示寬度為 255。顯示寬度與型別可以儲存的值範圍無關。
對於浮點和定點資料型別,M 是可以儲存的總位數。
對於數字資料型別(int、FLOAT、DOUBLE 和 DECIMAL),ZEROFILL 屬性已棄用;如果為數字列指定 ZEROFILL,則 MySQL 會自動將 UNSIGNED 屬性新增到該列。在未來版本的 MySQL 中刪除對它的支援。請考慮使用其他方法來產生此屬性的效果。例如,應用程式可以使用 LPAD() 函式將數字填充到所需的寬度,或者它們可以將格式化的數字儲存在 CHAR 列中。
SERIAL 是BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE 的別名。

bit(M)位值型別。M 表示每個值的位數,範圍為 1 到 64。如果省略 M,則預設值為 1。
BOOL, BOOLEAN 是 TINYINT(1) 的同義詞。值 0 被視為 false。非零值被視為 true;但是,值TRUE和FALSE分別只是1和0的別名。

整數型別   位元組 範圍(signed)     範圍(unsigned) 用途
TINYINT   1位元組 (-128,127)      (0,255) 小整數值
SMALLINT   2位元組 (-32768,32767)     (0,65535) 大整數值
MEDIUMINT 3位元組 (-8388608,8388607)    (0,16777215) 大整數值
INT或INTEGER 4位元組 (-2147483648,2147483647)   (0,4294967295) 大整數值:21億,10位數
BIGINT   8位元組 (-9223372036854775808,9223372036854775807) (0,18446744073709551615) 極大整數值 19位數
FLOAT   4位元組 (-3.4E+38,1.17E-38),  0, (1.17E-38,3.4E+38) 0,(1.17E-38,3.4E+38) 單精度浮點數值
DOUBLE   8位元組 (1.79E+308,2.22E-308),  0, (2.22E-308,1.79E+308) 0,(2.22E-308,1.79E+308) 雙精度浮點數值
DECIMAL/dec(fix用於其他系統相容) 對DECIMAL(M,D) 其中M表示十進位制數字總的個數,D表示小數點後面數字的位數。
M的預設取值為10,D預設取值為0。不帶引數時,等同decimal(10,0),帶一個引數時,D取預設值。
M的取值範圍為1~65,取0時會被設為預設值,超出範圍會報錯。
D的取值範圍為0~30,而且必須<=M,超出範圍會報錯。
所以,很顯然,當M=65,D=0時,可以取得最大和最小值。

DECIMAL(5,2),整數部分超出了範圍(如上面的例子中,新增數值為1000.01),MySql就會報錯,不允許存這樣的值。
小數點部分若超出範圍,就分以下情況:
若四捨五入後,整數部分沒有超出範圍,則只警告,但能成功操作並四捨五入刪除多餘的小數位後儲存。如999.994實際被儲存為999.99。
若四捨五入後,整數部分超出範圍,則MySql報錯,並拒絕處理。如999.995和-999.995都會報錯。

如果資料太大,可選方案1: 將小數,整數分開儲存成2個整數,取和存都分開儲存2個欄位。可選方案2:儲存成字串。

所有算術都是使用有符號 BIGINT 或 DOUBLE 值完成的,因此您不應使用大於 9223372036854775807(63 位)的無符號大整數,結果中的一些最後數字可能是錯誤的,因為在將 BIGINT 值轉換為 DOUBLE 時會出現舍入錯誤。
使用字串儲存 BIGINT 列中儲存精確的整數值。在這種情況下,MySQL 執行字串到數字的轉換,不涉及中間雙精度表示。

float(M,D): 一共M位整數,其中D位位於小數點後面。假如超過D位則四捨五入,即1.233四捨五入為1.23,1.237四捨五入為1.24。
FLOAT和DOUBLE中的M和D的取值預設都為0,會按照實際的精度來處理。
FLOAT和DOUBLE中如果M和D都有明確定義,其超出範圍後的處理同decimal。

M取值範圍為0~255。FLOAT只保證6位有效數字的準確性,所以FLOAT(M,D)中,M<=6時,數字通常是準確的。
double只保證16位有效數字的準確性,所以DOUBLE(M,D)中,M<=16時,數字通常是準確的。

mysql> CREATE TABLE t (b BIT(8));
mysql> INSERT INTO t SET b = b'11111111';
mysql> INSERT INTO t SET b = b'1010';
mysql> INSERT INTO t SET b = b'0101';
mysql> SELECT b+0, BIN(b+0), OCT(b+0), HEX(b+0) FROM t;
+------+----------+----------+----------+
| b+0 | BIN(b+0) | OCT(b+0) | HEX(b+0) |
+------+----------+----------+----------+
| 255 | 11111111 | 377 | FF |
| 10 | 1010 | 12 | A |
| 5 | 101 | 5 | 5 |
+------+----------+----------+----------+

MySQL 允許使用非標準語法:FLOAT(M,D) 或 REAL(M,D) 或 DOUBLE PRECISION(M,D),這裡,(M,D) 表示值總共最多可以儲存 M 位,其中 D 位可以位於小數點後。例如,定義為 FLOAT(7,4) 的列顯示為 -999.9999。MySQL 在儲存值時執行舍入,因此如果將 999.00009 插入 FLOAT(7,4) 列,則近似結果為 999.0001。

2、字串

MySQL 提供了8個基本的字串型別,分別:CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM 和SET等多種字串型別。
對於字串列(CHAR、VARCHAR和TEXT型別)的定義,MySQL 以字元定義長度。對於二進位制字串列(BINARY、VARBINARY和 BLOB 型別)的定義,MySQL 以位元組定義長度。CHAR(0) 也非常有用:定義為 CHAR(0)則只能接受值 NULL 和 '' (空字串)
BLOB最大長度為 65,535 (216 − 1) 位元組,text最大長度為 65,535 (216 − 1) 個字元。

字串型別 範圍 描述及儲存需求
CHAR(M) 最多255個字元 定長字串
VARCHAR(M) 最多65535個字元 變長字串
BINARY(M) 定長二進位制字串
VARBINARY 變長二進位制字串
TINYBLOB 可變長度,最多255個字元 不超過 255 個字元的二進位制字串
TINYTEXT 可變長度,最多255個字元 短文字字串
BLOB 可變長度,最多65535個字元 二進位制形式的長文字資料
TEXT 可變長度,最多65535個字元 長文字資料
MEDIUMBLOB 最多0-16777215個字元 二進位制形式的中等長度文字資料
MEDIUMTEXT 最多0-16777215個字元 中等長度文字資料
LOGNGBLOB 最多0-4294967295個字元 二進位制形式的極大文字資料
LONGTEXT 最多0-4294967295個字元 極大文字資料


Value CHAR(4)   所需儲存 VARCHAR(4) 所需儲存
''    ' '   4 bytes   '' 1 byte
'ab'   'ab '   4 bytes   'ab' 3 bytes
'abcd' 'abcd'  4 bytes   'abcd' 5 bytes
'abcdefgh' 'abcd'  4 bytes   'abcd' 5 bytes

1.char(n) 若存入字元數小於n,則以空格補於其後,查詢之時再將空格去掉。所以char型別儲存的字串末尾不能有空格,varchar不限於此。
2.char(n) 固定長度,char(4)不管是存入幾個字元,都將佔用4個位元組,varchar是存入的實際字元數+1個位元組(n<=255)或2個位元組(n>255),所以varchar(4),存入3個字元將佔用4個位元組。
3.varchar為可變長度字串,在utf8編碼的資料庫中其長度範圍為0~21844。

MySQL要求一個行的定義長度不能超過65535即64K
(1)對於未指定varchar欄位not null的欄位,會有1個位元組專門表示該欄位是否為null。
(2)varchar(M),當M範圍為0<=M<=255時會專門有一個位元組記錄varchar型字串長度,當M>255時會專門有兩個位元組記錄varchar型字串的長度,把這一點和上一點結合,那麼65535個位元組實際可用的為65535-3=65532個位元組
(3)所有英文無論其編碼方式,都佔用1個位元組,但對於gbk編碼,一個漢字佔兩個位元組,因此最大M=65532/2=32766;對於utf8編碼,一個漢字佔3個位元組,因此最大M=65532/3=21844。
(4)對於utfmb4編碼方式,1個字元最大可能佔4個位元組,那麼varchar(M),M最大為65532/4=16383。
同樣的,上面是表中只有varchar型資料的情況,如果表中同時存在int、double、char這些資料,需要把這些資料所佔據的空間減去,才能計算varchar(M)型資料M最大等於多少。


text和varchar是一組既有區別又有聯絡的資料型別,其聯絡在於當varchar(M)的M大於某些數值時,varchar會自動轉為text:

M>255時轉為tinytext
M>500時轉為text
M>20000時轉為mediumtext

所以過大的內容varchar和text沒有區別,同事varchar(M)和text的區別在於:

單行64K即65535位元組的空間,varchar只能用63352/65533個位元組,但是text可以65535個位元組全部用起來
text可以指定text(M),但是M無論等於多少都沒有影響
text不允許有預設值,varchar允許有預設值。
varchar和text兩種資料型別,使用建議是能用varchar就用varchar而不用text(儲存效率高),varchar(M)的M有長度限制,之前說過,如果大於限制,可以使用mediumtext(16M)或者longtext(4G)。

至於text和blob,text儲存的是字串而blob儲存的是二進位制字串,簡單說blob是用於儲存例如圖片、音影片這種檔案的二進位制資料的。
ENUM 列最多可以有 65,535 個不同的元素。


3、日期和時間型別
表示時態值的日期和時間資料型別為 DATE、TIME、DATETIME、TIMESTAMP 和 YEAR。每個時間型別都有一個有效值範圍,以及一個“零”值,當您指定 MySQL 無法表示的無效值時,可以使用該值。
2位的年份,MySQL預設70-99 範圍內的年份值變為 1970-1999。00-69 範圍內的年份值將變為 2000-2069。
預設情況下,當 MySQL 遇到日期或時間型別的值超出範圍或對該型別無效時,它會將該值轉換為該型別的“零”值。例外情況是,超出範圍的 TIME 值被剪下到 TIME 範圍的相應端點。

型別 大小(位元組) 範圍 格式 用途
DATE 4 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
TIME 3 '-838:59:59'/'838:59:59' HH:MM:SS 時間值或持續時間
YEAR 1 1901/2155 YYYY 年份值
DATETIME 8 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和時間值
TIMESTAMP 4 1970-01-01 00:00:00/2038-01-19 03:14:07 YYYYMMDD HHMMSS 混合日期和時間值,時間戳

MySQL在5.6.4版本之後,TIMESTAMP和DATETIME支援到微秒。
TIMESTAMP會根據系統時區進行轉換,DATETIME則不會,一般使用TIMESTAMP國際化

MySQL 日期、時間相減函式:datediff(date1,date2), timediff(time1,time2)

MySQL datediff(date1,date2):兩個日期相減 date1 - date2,返回天數。
select datediff('2008-08-08', '2008-08-01'); -- 7
select datediff('2008-08-01', '2008-08-08'); -- -7

MySQL timediff(time1,time2):兩個日期相減 time1 - time2,返回 time 差值。
select timediff('2008-08-08 08:08:08', '2008-08-08 00:00:00'); -- 08:08:08
select timediff('08:08:08', '00:00:00'); -- 08:08:08

注意:timediff(time1,time2) 函式的兩個引數型別必須相同。
此外,如果 explicit_defaults_for_timestamp 系統變數被禁用,則可以透過為其分配 NULL 值來將任何 TIMESTAMP(而不是 DATETIME)列初始化或更新為當前日期和時間,除非已使用 NULL 屬性定義該列以允許 NULL 值。

列定義中使用 DEFAULT CURRENT_TIMESTAMP 或 ON UPDATE CURRENT_TIMESTAMP 子句。CURRENT_TIMESTAMP CURRENT_TIMESTAMP()、NOW()、LOCALTIME、LOCALTIME()、LOCALTIMESTAMP和 LOCALTIMESTAMP()相同。

TIMESTAMP 的預設值為 0,除非使用 NULL 屬性定義,在這種情況下,預設值為 NULL。
CREATE TABLE t1 (
ts1 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- default 0
ts2 TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP -- default NULL
);

除非使用 NOT NULL 屬性定義,否則 DATETIME 的預設值為 NULL,not null定義下預設值為 0。
CREATE TABLE t1 (
dt1 DATETIME ON UPDATE CURRENT_TIMESTAMP, -- default NULL
dt2 DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP -- default 0
);

如果 TIMESTAMP 或 DATETIME 列定義在任何地方都包含顯式的小數秒精度值,則必須在整個列定義中使用相同的值。這是允許的:
CREATE TABLE t1 (
ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
);

不允許這樣做:
CREATE TABLE t1 (
ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(3)
);

MySQL 對 TIME、DATETIME 和 TIMESTAMP 值提供秒的小數部分支援,精度高達微秒(6 位):
CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) );
INSERT INTO fractest VALUES
('17:51:04.777', '2018-09-08 17:51:04.777', '2018-09-08 17:51:04.777');

時間值將插入到表中,並進行四捨五入:發生此類舍入時,不會給出警告或錯誤。
mysql> SELECT * FROM fractest;
+-------------+------------------------+------------------------+
| c1 | c2 | c3 |
+-------------+------------------------+------------------------+
| 17:51:04.78 | 2018-09-08 17:51:04.78 | 2018-09-08 17:51:04.78 |
+-------------+------------------------+------------------------+

要改為插入帶有截斷的值,請啟用 TIME_TRUNCATE_FRACTIONAL SQL 模式:
SET @@sql_mode = sys.list_add(@@sql_mode, 'TIME_TRUNCATE_FRACTIONAL');

mysql> SELECT * FROM fractest;
+-------------+------------------------+------------------------+
| c1 | c2 | c3 |
+-------------+------------------------+------------------------+
| 17:51:04.77 | 2018-09-08 17:51:04.77 | 2018-09-08 17:51:04.77 |
+-------------+------------------------+------------------------+


================================= 8.0 空間+json ==================
8.0的新型別
空間型別:geometry point linestring polygon
空間集合:geometrycollection multipoint multilinestring multipolygon

GEOMETRY 可以儲存任何型別的幾何值。其他單值型別(POINT、LINESTRING 和 POLYGON)將其值限制為特定的幾何型別。
GEOMETRYCOLLECTION 可以儲存任何型別的物件集合。其他集合型別(MULTIPOINT、MULTILINESTRING 和 MULTIPOLYGON)將集合成員限制為具有特定幾何型別的集合成員。

CREATE TABLE geom (
p POINT SRID 0,
g GEOMETRY NOT NULL SRID 4326
);
如果空間列為 NOT NULL 並且具有特定的 SRID,則可以在空間列上建立 SPATIAL 索引.


JSON型別: json

儲存 JSON 文件所需的空間與 LONGBLOB 或 LONGTEXT 大致相同;儲存在 JSON 列中的任何 JSON 文件的大小都限制為 max_allowed_packet 系統變數的值。

詳細請看:mysql 8.0 新增資料型別 json

相關文章