當 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 模式,則會發生錯誤且欄保持不變。