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


12.25.3 式の処理

高精度計算では、可能な場合は常に、厳密値数値は与えられたとおりに使用されます。 たとえば、比較での数値は、値を変更することなく正確に指定されたとおりに使用されます。 厳密な SQL モードでは、厳密値データ型 (DECIMAL または整数) を持つカラムへの INSERT の場合、数値の厳密値がそのカラムの範囲内にあれば、その数値が厳密値で挿入されます。 取得されると、その値は、挿入された値と同じになるはずです。 (厳密な SQL モードが有効になっていない場合は、INSERT での切り捨てが許可されます。)

数値式の処理は、その式にどのような種類の値が含まれているかによって異なります。

  • 近似値が存在する場合、その式は近似値であるため、浮動小数点演算を使用して評価されます。

  • 近似値が存在しない場合、その式には厳密値のみが含まれています。 いずれかの厳密値に小数部 (小数点に続く値) が含まれている場合、その式は DECIMAL の正確な演算を使用して評価され、精度は 65 桁になります。 正確なという用語は、バイナリで表すことができる精度の制限に従います。 たとえば、1.0/3.0 は 10 進数表記で .333... と近似できますが、厳密値数値として記述されないため、(1.0/3.0)*3.0 は正確には 1.0 に評価されません。

  • それ以外の場合、式には整数値のみが含まれています。 その式は厳密値であり、整数演算を使用して評価され、精度は BIGINT (64 ビット) と同じになります。

数値式に文字列が含まれている場合、その文字列は倍精度浮動小数点値に変換され、その式は近似値になります。

数値カラムへの挿入は、sql_mode システム変数によって制御される SQL モードによって影響を受けます。 (セクション5.1.11「サーバー SQL モード」を参照してください。) 次の説明では、厳密モード (STRICT_ALL_TABLES または STRICT_TRANS_TABLES モード値によって選択されます) および ERROR_FOR_DIVISION_BY_ZERO について触れています。 すべての制限を有効にするには、単純に、厳密モード値と ERROR_FOR_DIVISION_BY_ZERO の両方を含む TRADITIONAL モードを使用できます。

SET sql_mode='TRADITIONAL';

数値が正確な型のカラム (DECIMAL または整数) に挿入された場合、その数値がカラムの範囲および精度内にあれば、正確な値とともに挿入されます。

小数部の桁数が多すぎる場合、端数処理が行われ、ノートが生成されます。 丸めは、セクション12.25.4「丸め動作」で説明されているとおりに実行されます。 小数部の丸めによる切捨ては、厳密モードでもエラーではありません。

整数部の桁数が多すぎる場合、値は大きすぎる (範囲外) ため、次のように処理されます:

  • 厳密モードが有効になっていない場合は、その値がもっとも近い正当な値に切り捨てられ、警告が生成されます。

  • 厳密モードが有効になっている場合は、オーバーフローエラーが発生します。

DECIMAL リテラルの場合、65 桁の精度制限に加えて、リテラルのテキストの長さに制限があります。 値が約 80 文字を超えると、予期しない結果が発生する可能性があります。 例:

mysql> SELECT
       CAST(0000000000000000000000000000000000000000000000000000000000000000000000000000000020.01 AS DECIMAL(15,2)) as val;
+------------------+
| val              |
+------------------+
| 9999999999999.99 |
+------------------+
1 row in set, 2 warnings (0.00 sec)

mysql> SHOW WARNINGS;
+---------+------+----------------------------------------------+
| Level   | Code | Message                                      |
+---------+------+----------------------------------------------+
| Warning | 1292 | Truncated incorrect DECIMAL value: '20'      |
| Warning | 1264 | Out of range value for column 'val' at row 1 |
+---------+------+----------------------------------------------+
2 rows in set (0.00 sec)

アンダーフローは検出されないため、アンダーフローの処理は定義されていません。

数値カラムへの文字列の挿入では、その文字列に非数値の内容が含まれている場合、文字列から数値への変換は次のように処理されます。

  • 数値で始まらない文字列を数値として使用することはできないため、この文字列により厳密モードではエラーが生成され、それ以外の場合は警告が生成されます。 これには、空の文字列が含まれます。

  • 数値で始まる文字列は変換できますが、後続の非数値の部分は切り捨てられます。 その切り捨てられた部分にスペース以外の文字が含まれている場合、厳密モードではエラーが生成され、それ以外の場合は警告が生成されます。

デフォルトでは、0 による除算によって NULL の結果が生成され、警告は生成されません。 SQL モードを適切に設定することにより、0 による除算を制限できます。

ERROR_FOR_DIVISION_BY_ZERO SQL モードが有効になっている場合、MySQL は、0 による除算を次の異なった方法で処理します。

  • 厳密モードが有効になっていない場合は、警告が発生します。

  • 厳密モードが有効になっている場合は、0 による除算を含む挿入と更新が禁止され、エラーが発生します。

つまり、0 による除算を実行する式を含む挿入や更新をエラーとして処理できますが、それには、厳密モードに加えて ERROR_FOR_DIVISION_BY_ZERO が必要です。

次のステートメントがあるとします。

INSERT INTO t SET i = 1/0;

次に、厳密モードと ERROR_FOR_DIVISION_BY_ZERO モードの各組み合わせに対する動作を示します。

sql_mode 結果
'' (デフォルト) 警告なし、エラーなし。iNULL に設定されます。
厳密 警告なし、エラーなし。iNULL に設定されます。
ERROR_FOR_DIVISION_BY_ZERO 警告あり、エラーなし。iNULL に設定されます。
厳密、ERROR_FOR_DIVISION_BY_ZERO エラー状態。行は挿入されません。

関連キーワード:  関数, モード, 数値, 処理, 空間, リファレンス, エラー, 精度, 挿入, 生成