本文是本人在閱讀MYSQL5.7參考手冊11.2節時翻譯的譯文,若有差錯,歡迎你們指正html
11.2.1 整數類型 (存儲精確值) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINTmysql
11.2.2 定點數類型 (存儲精確值) - DECIMAL, NUMERICsql
11.2.3 浮點數類型 (存儲近似值) - FLOAT, DOUBLEbash
11.2.4 BIT類型 - 存儲位值ui
11.2.5 數值類型的屬性spa
11.2.6 數值範圍超出和計算溢出的處理操作系統
Mysql 支持SQL標準的整數類型:INTEGER(INT)和SMALLINT。做爲擴展,MySQL也支持TINYINT, MEDIUMINT,和BIGINT,下面的表格展現了Mysql不一樣整數類型的取值範圍和佔用存儲空間翻譯
DECIMAL和NUMERIC用於存儲一個精確的值.若是要確保存儲值的精確性,好比金融數據,那麼你應該使用這些類型。在MySQL中,NUMERIC與DECIMAL等效,因此下面關於DECIMAL的描述一樣適用於NUMERIC。3d
MySQL以二進制存儲DECIMAL。詳情請閱讀12.22節「Precision Math」.code
聲明一個DECIMAL列時,一般能夠指定精度(precision)和刻度(scale);
例如:salary DECIMAL(5,2)
在這個例子中,5表示精度(precision),2表示刻度(scale),精度表示能存儲的總位數,刻度表示小數點以後能存儲的有效位
SQL標準規定DECIMAL(5,2)必須能存儲任何總位數爲5位且精度爲小數點後兩位的數值,因此salary的能存儲的範圍是[-999.99,999.99]
在SQL標準規範中,表達式DECIMAL(M)與DECIMAL(M,0)等價,表達式中容許指定M的值,MySQL支持這兩種形式的語法,M的默認值是10。
若是刻度爲0,那麼值中將不包含小數點和小數部分。
DECIMAL能表示的最大位數爲65,可是實際的存儲範圍受到定義的精度和刻度限制。當爲某個DECIMAL列賦值,該值的小數點後位數超過指定的刻度所容許的位數時,該值將轉換爲該刻度。(精確的行爲是特定於操做系統的,但一般效果是截斷到容許的位數。)
BIT類型類型用來存儲位信息,BIT(M)容許存儲M位數據,M的範圍是[1-64]
注意:
- 對於涉及到表達式或者UNION查詢時,ZEROFILL屬性將會被忽略
- 若是你存儲了一個大於顯示寬度的整數值,當進行一些複雜的jion操做時你可能會遇到一些問題,這種狀況下,MySQL假定數據值符合列顯示寬度
全部的整數類型都擁有一個可選的(非標準的)UNSIGNED屬性,unsigned類型可用來存儲非負數或者存儲一個更大的數值。舉例來講:若是一個INT類型的列聲明爲UNSIGNED,那麼它能表示的範圍大小相同,可是表示範圍的值由[-2147483648,2147483647]變成了[0 ,4294967295]
浮點數和定點數也能夠和整數同樣被聲明爲UNSIGNED,這個屬性能夠防止負數存儲到列中,與整數不一樣的是它們的取值上限仍是和原來同樣
若是你爲一個列指定ZEROFILL屬性,那麼MySQL會自動爲其添加UNSIGNED屬性
整數和浮點數類型都具備AUTO_INCREMENT屬性,當你插入一個NULL值到具備AUTO_INCREMENT屬性的列時,這個列的值將被設置爲AUTO_INCREMENT序列中的下一個值,也就是value+1,value取這個表中該列的最大值(AUTO_INCREMENT序列由1開始.)
注意:
- 向這個列中插入0等同於插入NULL,除非開啓SQL mode的NO_AUTO_VALUE_ON_ZERO屬性
- 當插入一個NULL值生成AUTO_INCREMENT時須要爲列賦予NOT NULL屬性,若是這個列被聲明爲容許爲NULL,那麼將會插入NULL。爲這個列插入一個值時這個值同時也會刷新AUTO_INCREMENT序列,確保下一個序列值的與插入的值順序一致
當MySQL存儲一個超出範圍的值到數值類型的列時,處理結果取決於當時SQL mode的設置:
假設咱們定義一個表t1:
CREATE TABLE t1 (i1 TINYINT, i2 TINYINT UNSIGNED);
複製代碼
在啓用嚴格的SQL mode時,會發生一個錯誤
mysql> SET sql_mode = 'TRADITIONAL';
mysql> INSERT INTO t1 (i1, i2) VALUES(256, 256);
ERROR 1264 (22003): Out of range value for column 'i1' at row 1
mysql> SELECT * FROM t1;
Empty set (0.00 sec)
複製代碼
在未啓用嚴格的SQL mode時,會發生一個警告
mysql> SET sql_mode = '';
mysql> INSERT INTO t1 (i1, i2) VALUES(256, 256);
mysql> SHOW WARNINGS;
+---------+------+---------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------+
| Warning | 1264 | Out of range value for column 'i1' at row 1 |
| Warning | 1264 | Out of range value for column 'i2' at row 1 |
+---------+------+---------------------------------------------+
mysql> SELECT * FROM t1;
+------+------+
| i1 | i2 |
+------+------+
| 127 | 255 |
+------+------+
複製代碼
若是未啓用嚴格的SQL mode,列的轉換時發生ALTER TABLE, LOAD DATA, UPDATE, 和多行的插入的警告, 在嚴格的SQL mode下,這些操做會失敗,值不會被插入或改變,這還取決於這個表是不是事務表或一些其餘因素。詳情請見5.1.10章 Server SQL Modes。
這段水平有限,翻譯的很牽強,官方原文:
When strict SQL mode is not enabled, column-assignment conversions that occur due to clipping are reported as warnings for ALTER TABLE, LOAD DATA, UPDATE, and multiple-row INSERT statements. In strict mode, these statements fail, and some or all the values are not inserted or changed, depending on whether the table is a transactional table and other factors. For details, see Section 5.1.10, 「Server SQL Modes」.
表達式求值期間發生溢出將致使錯誤,例如signed BIGINT的最大值是9223372036854775807,因此下面的表達式會產生錯誤
mysql> SELECT 9223372036854775807 + 1;
ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807 + 1)'
複製代碼
爲了使得這個表達式正確,將值強轉成unsigned
mysql> SELECT CAST(9223372036854775807 AS UNSIGNED) + 1;
+-------------------------------------------+
| CAST(9223372036854775807 AS UNSIGNED) + 1 |
+-------------------------------------------+
| 9223372036854775808 |
+-------------------------------------------+
複製代碼
是否溢出取決於操做數的範圍,因此另一個解決方法是使用定點數,由於DECIMAL的取值範圍是大於整數的
mysql> SELECT 9223372036854775807.0 + 1;
+---------------------------+
| 9223372036854775807.0 + 1 |
+---------------------------+
| 9223372036854775808.0 |
+---------------------------+
複製代碼
兩個整數相減,而其中一個是無符號數時,結果會返回一個無符號數,可是若是結果是負數,那麼會發生一個錯誤
mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0 as unsigned) - 1)'
複製代碼
若是SQL mode啓用NO_UNSIGNED_SUBTRACTION,那麼結果將是一個負數
mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
| -1 |
+-------------------------+
複製代碼
若是使用此類操做的結果更新無符號整數列,則將結果設置爲列類型的最大值,若是啓用no_unsigned_subtract,則將結果裁剪爲0。若是啓用了嚴格的SQL mode,則會發生錯誤,而且列保持不變
MySQL支持全部SQL標準數值類型,這些類型包括精確的數值類型(INTEGER, SMALLINT, DECIMAL,和NUMERIC),也包含近似值數據類型(FLOAT, REAL, and DOUBLE PRECISION)。對於MYSQL來講,INT和INTERGER類型是等效的,DEX和FIXED與DECIMAL類型是等效的。PRECISION和DOUBLE類型也是等效的。除非SQL_MODE啓用REAL_AS_FLOAT,不然REAL和DOUBLE PRECISION一樣是等效的。
BIT類型存儲位數據,僅支持MyISAM, MEMORY, InnoDB,和NDB引擎的表。
有關MySQL如何處理向列存儲超範圍值和表達式計算期間溢出細節請閱讀11.2.6節「Out-of-Range and Overflow Handling」。
關於不一樣數值類型須要佔用的存儲空間請閱讀11.8節, 「Data Type Storage Requirements」。
計算結果的類型取決於計算的參數類型和對他們進行的操做,具體信息見12.6.1節 「Arithmetic Operators」。