このページは機械翻訳したものです。
このセクションでは、MySQL での精度の高い数学的クエリー結果を示す例をいくつか示します。 これらの例は、セクション12.25.3「式の処理」およびセクション12.25.4「丸め動作」で説明されている原則を示しています。
例 1 数値は、可能であれば、指定されたとおりにその厳密値で使用されます。
Press CTRL+C to copymysql> SELECT (.1 + .2) = .3; +----------------+ | (.1 + .2) = .3 | +----------------+ | 1 | +----------------+
浮動小数点値の場合、結果は不正確です。
Press CTRL+C to copymysql> SELECT (.1E0 + .2E0) = .3E0; +----------------------+ | (.1E0 + .2E0) = .3E0 | +----------------------+ | 0 | +----------------------+
厳密値と近似値の処理の違いを確認するための別の方法として、合計値に小さい数値を何回も加える方法があります。 ある変数に .0001
を 1,000 回加える次のストアドプロシージャーを考えてみます。
Press CTRL+C to copyCREATE PROCEDURE p () BEGIN DECLARE i INT DEFAULT 0; DECLARE d DECIMAL(10,4) DEFAULT 0; DECLARE f FLOAT DEFAULT 0; WHILE i < 10000 DO SET d = d + .0001; SET f = f + .0001E0; SET i = i + 1; END WHILE; SELECT d, f; END;
論理的には、d
と f
の両方の合計値が 1 になるはずですが、それは 10 進数の計算にしか当てはまりません。 浮動小数点の計算では、小さなエラーが発生します。
Press CTRL+C to copy+--------+------------------+ | d | f | +--------+------------------+ | 1.0000 | 0.99999999999991 | +--------+------------------+
例 2 乗算は、標準 SQL に必要なスケールで実行されます。 つまり、スケール S1
と S2
を持つ 2 つの数値 X1
と X2
の場合、結果のスケールは
になります。
S1
+ S2
Press CTRL+C to copymysql> SELECT .01 * .01; +-----------+ | .01 * .01 | +-----------+ | 0.0001 | +-----------+
例 3 厳密値数値に対する丸め動作は、適切に定義されています。
丸め動作 (たとえば、ROUND()
関数を使用した動作) は、ベースとなる C ライブラリの実装には依存しません。つまり、その結果は各プラットフォームにわたって一貫性があります。
-
厳密値カラム (
DECIMAL
と整数) および厳密値数値に対する丸めでは、「四捨五入」ルールが使用されます。 小数部が .5 以上の値は、次に示すようにゼロから最も近い整数に丸められます:Press CTRL+C to copymysql> SELECT ROUND(2.5), ROUND(-2.5); +------------+-------------+ | ROUND(2.5) | ROUND(-2.5) | +------------+-------------+ | 3 | -3 | +------------+-------------+
-
浮動小数点値に対する丸めでは、C ライブラリが使用されます。これは、多くのシステムでは「偶数丸め」ルールを使用します。 2 つの整数の間に小数部が完全に半分の値がある場合、最も近い偶数に丸められます:
Press CTRL+C to copymysql> SELECT ROUND(2.5E0), ROUND(-2.5E0); +--------------+---------------+ | ROUND(2.5E0) | ROUND(-2.5E0) | +--------------+---------------+ | 2 | -2 | +--------------+---------------+
例 4 厳密モードでは、カラムの範囲を外れている値を挿入すると、正当な値への切り捨てではなく、エラーが発生します。
MySQL が厳密モードで実行されていない場合は、正当な値への切り捨てが発生します。
Press CTRL+C to copymysql> SET sql_mode=''; Query OK, 0 rows affected (0.00 sec) mysql> CREATE TABLE t (i TINYINT); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO t SET i = 128; Query OK, 1 row affected, 1 warning (0.00 sec) mysql> SELECT i FROM t; +------+ | i | +------+ | 127 | +------+ 1 row in set (0.00 sec)
ただし、厳密モードが有効になっている場合は、エラーが発生します。
Press CTRL+C to copymysql> SET sql_mode='STRICT_ALL_TABLES'; Query OK, 0 rows affected (0.00 sec) mysql> CREATE TABLE t (i TINYINT); Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO t SET i = 128; ERROR 1264 (22003): Out of range value adjusted for column 'i' at row 1 mysql> SELECT i FROM t; Empty set (0.00 sec)
例 5: 厳密モードで ERROR_FOR_DIVISION_BY_ZERO
が設定されている場合は、0 による除算によって NULL
の結果ではなく、エラーが発生します。
非厳密モードでは、0 による除算によって NULL
の結果が生成されます。
Press CTRL+C to copymysql> SET sql_mode=''; Query OK, 0 rows affected (0.01 sec) mysql> CREATE TABLE t (i TINYINT); Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO t SET i = 1 / 0; Query OK, 1 row affected (0.00 sec) mysql> SELECT i FROM t; +------+ | i | +------+ | NULL | +------+ 1 row in set (0.03 sec)
ただし、適切な SQL モードが有効になっている場合、0 による除算はエラーになります。
Press CTRL+C to copymysql> SET sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO'; Query OK, 0 rows affected (0.00 sec) mysql> CREATE TABLE t (i TINYINT); Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO t SET i = 1 / 0; ERROR 1365 (22012): Division by 0 mysql> SELECT i FROM t; Empty set (0.01 sec)
例 6 厳密値リテラルは、厳密値として評価されます。
近似値リテラルは浮動小数点を使用して評価されますが、正確な値リテラルは DECIMAL
として処理されます:
Press CTRL+C to copymysql> CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b; Query OK, 1 row affected (0.01 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> DESCRIBE t; +-------+-----------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-----------------------+------+-----+---------+-------+ | a | decimal(2,1) unsigned | NO | | 0.0 | | | b | double | NO | | 0 | | +-------+-----------------------+------+-----+---------+-------+ 2 rows in set (0.01 sec)
例 7 集約関数への引数が厳密値数値型である場合は、その結果も、少なくとも引数と同じスケールを持つ厳密値数値型になります。
これらのステートメントを考慮してください。
Press CTRL+C to copymysql> CREATE TABLE t (i INT, d DECIMAL, f FLOAT); mysql> INSERT INTO t VALUES(1,1,1); mysql> CREATE TABLE y SELECT AVG(i), AVG(d), AVG(f) FROM t;
結果が倍精度値になるのは浮動小数点引数の場合だけです。 厳密値型引数の場合は、結果も厳密値型になります。
Press CTRL+C to copymysql> DESCRIBE y; +--------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+---------------+------+-----+---------+-------+ | AVG(i) | decimal(14,4) | YES | | NULL | | | AVG(d) | decimal(14,4) | YES | | NULL | | | AVG(f) | double | YES | | NULL | | +--------+---------------+------+-----+---------+-------+
結果が倍精度値になるのは浮動小数点引数の場合だけです。 厳密値型引数の場合は、結果も厳密値型になります。