當 MySQL 在數值欄位中儲存超出該欄位資料類型允許範圍的值時,結果取決於當時生效的 SQL 模式。
如果啟用嚴格 SQL 模式,MySQL 會拒絕超出範圍的值並產生錯誤,並且根據 SQL 標準,插入會失敗。
如果未啟用限制模式,MySQL 會將該值裁剪為欄位資料類型範圍的適當端點,並儲存結果值。
當超出範圍的值被賦值給整數欄位時,MySQL 會儲存表示欄位資料類型範圍對應端點的值。
當浮點或定點欄位被賦予超過指定 (或預設) 精確度和比例所暗示的範圍的值時,MySQL 會儲存表示該範圍對應端點的值。
假設表格 t1
具有以下定義:
CREATE TABLE t1 (i1 TINYINT, i2 TINYINT UNSIGNED);
在啟用嚴格 SQL 模式的情況下,會發生超出範圍的錯誤。
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 模式的情況下,會發生裁剪並顯示警告。
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 模式時,由於裁剪而發生的欄位指派轉換會以警告的形式回報給 ALTER TABLE
、LOAD DATA
、UPDATE
和多列 INSERT
陳述式。在嚴格模式下,這些陳述式會失敗,並且某些或所有值不會被插入或變更,具體取決於表格是否為交易表格和其他因素。詳細資訊請參閱第 7.1.11 節「伺服器 SQL 模式」。
數值運算式評估期間的溢位會導致錯誤。例如,最大的帶號 BIGINT
值為 9223372036854775807,因此以下運算式會產生錯誤:
mysql> SELECT 9223372036854775807 + 1;
ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807 + 1)'
若要使此操作成功,請將值轉換為無號:
mysql> SELECT CAST(9223372036854775807 AS UNSIGNED) + 1;
+-------------------------------------------+
| CAST(9223372036854775807 AS UNSIGNED) + 1 |
+-------------------------------------------+
| 9223372036854775808 |
+-------------------------------------------+
是否發生溢位取決於運算元的範圍,因此處理上述運算式的另一種方法是使用精確值運算,因為 DECIMAL
值具有比整數更大的範圍:
mysql> SELECT 9223372036854775807.0 + 1;
+---------------------------+
| 9223372036854775807.0 + 1 |
+---------------------------+
| 9223372036854775808.0 |
+---------------------------+
整數值之間的減法,其中一個是 UNSIGNED
類型,預設會產生無號結果。如果結果本應為負數,則會產生錯誤:
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)'
如果啟用 NO_UNSIGNED_SUBTRACTION
SQL 模式,則結果為負數:
mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
| -1 |
+-------------------------+
如果此類操作的結果用於更新 UNSIGNED
整數欄位,則結果會被裁剪為欄位類型的最大值,如果啟用 NO_UNSIGNED_SUBTRACTION
,則會被裁剪為 0。如果啟用嚴格 SQL 模式,則會發生錯誤並且欄位保持不變。