文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  超出範圍與溢位處理

13.1.7 超出範圍與溢位處理

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