最近一段運行良好的代碼突然無法運行,報錯:
MySQL said: Documentation
1690 - BIGINT UNSIGNED value is out of range in
經過查詢,發現這個錯誤的原因是兩個時間字段進行減法運算時,如果有一個時間為0000-00-00時造成的,根本原因是因為這樣減法的結果會超過Mysql數值字段的范圍,從而觸發1690報錯。
ERROR 1690 Out-of-Range
當Mysql中的數字字段存儲了一個超過允許范圍的數字時,會觸發1690 Out of Range錯誤,是否觸發錯誤取決於SQL運行時的模式:
當標准 Standar Mode 或 Strict Mode 運行時,數據插入會失敗
當非限制模式 No Restrictive 運行時,Mysql將數值轉化為范圍允許內的最大或最小值進行存儲
解決方法
SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
在進行計算時,首先執行上面的語句,可以避免減法運算過程中的錯誤。在Mysql文檔中,明確指出兩個整數進行相減運算的結果是一個無符號數,在Mysql 5.5.5 之前,如果產生一個負數,mysql會將這個數轉換為一個最大的數值。
mysql> SET sql_mode = '';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
| 18446744073709551615 |
+-------------------------+
自Mysql 5.5.5 之后,如果產生一個負數,則會產生一個錯誤 ERROR 1690。
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
SQL_MODE默認為空,有很多的選項,建議在生產環境中設置成嚴格的MODE,這樣可以在運維期間避免很多麻煩。
參考資料
1、Server SQL Modes
2、Out of Range and Overflow Handling
3、Mysql SQL_MODE