MySQL 8.0 リファレンスマニュアル


MySQL 8.0 リファレンスマニュアル  /  ...  /  範囲外およびオーバーフローの処理

11.1.7 範囲外およびオーバーフローの処理

MySQL が、カラムデータ型の許可できる範囲外にある数値カラムに値を格納すると、結果は、その時点で有効な SQL モードによって異なります。

  • 厳密な SQL モードが有効な場合、SQL 標準に従って、MySQL は範囲外の値を拒否してエラーを表示し、挿入は失敗します。

  • 制限モードが有効になっていない場合、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 ステートメントの警告としてレポートされます。 厳密モードでは、これらのステートメントは失敗し、テーブルがトランザクションテーブルかどうかやその他の要因に応じて、一部またはすべての値が挿入または変更されません。 詳細は、セクション5.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 |
+-------------------------------------------+

オーバーフローが起きるかどうかはオペランドの範囲に応じて異なります。したがって、前述の式を処理するもう 1 つの方法として、DECIMAL 値に整数より大きな範囲があるので正確な値の演算を使用します。

mysql> SELECT 9223372036854775807.0 + 1;
+---------------------------+
| 9223372036854775807.0 + 1 |
+---------------------------+
|     9223372036854775808.0 |
+---------------------------+

一方が UNSIGNED 型のときに 2 つの整数値の間で減算を行うと、デフォルトでは符号なしの結果が生成されます。 それ以外の場合は、エラーが発生します:

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 モードが有効になっている場合は、エラーが発生し、カラムは変わりません。


関連キーワード:  範囲, カラム, クラス, UNSIGNED, モード, 数値, 空間, 発生, エラー, range