Spec-Zone .ru
спецификации, руководства, описания, API
|
Этот раздел обеспечивает некоторые примеры, которые показывают математические результаты запроса точности в MySQL 5.7. Эти примеры демонстрируют принципы, описанные в Разделе 12.19.3, "Обработка Выражения", и Раздел 12.19.4, "Округление Поведения".
Пример 1. Числа используются с их точным значением как дано когда возможный:
mysql> SELECT (.1 + .2) = .3;
+----------------+| (.1 + .2) = .3 |+----------------+| 1 |+----------------+
Для значений с плавающей точкой результаты неточны:
mysql> SELECT (.1E0 + .2E0) = .3E0;
+----------------------+| (.1E0 + .2E0) = .3E0 |+----------------------+| 0 |+----------------------+
Другой способ видеть различие в обработке точного и приближенного значения состоит в том, чтобы добавить
небольшое число к сумме много раз. Рассмотрите следующую хранимую процедуру, которая добавляет .0001
к переменным 1 000 времена.
CREATE 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, но это
- истина только для десятичного вычисления. Вычисление с плавающей точкой представляет маленькие ошибки:
+--------+------------------+| d | f |+--------+------------------+| 1.0000 | 0.99999999999991 |+--------+------------------+
Пример 2. Умножение выполняется с масштабом, требуемым стандартным
SQL. Таким образом, для двух чисел X1
и X2
у этого есть масштаб S1
и S2
,
масштаб результата
:
S1
+ S2
mysql> SELECT .01 * .01;
+-----------+| .01 * .01 |+-----------+| 0.0001 |+-----------+
Пример 3. Округление поведения для чисел точного значения четко определено:
Округление поведения (например, с ROUND()
функция), независимо от реализации базовой библиотеки C, что означает, что результаты являются непротиворечивыми
от платформы до платформы.
Округление для точных столбцов значений (DECIMAL
и целое число), и точно оцененные числа использует "круглую половину далеко от нулевого"
правила. Значения с дробной частью.5 или больше округляются далеко от нуля до самого близкого целого
числа, как показано здесь:
mysql> SELECT ROUND(2.5),
ROUND(-2.5);
+------------+-------------+| ROUND(2.5) | ROUND(-2.5) |+------------+-------------+| 3 | -3 |+------------+-------------+
Округление для значений с плавающей точкой пользуется библиотекой C, которая на многих системах использует "вокруг для самого близкого даже" правила. Значения с любой дробной частью на таких системах округляются к самому близкому даже целое число:
mysql> SELECT ROUND(2.5E0),
ROUND(-2.5E0);
+--------------+---------------+| ROUND(2.5E0) | ROUND(-2.5E0) |+--------------+---------------+| 2 | -2 |+--------------+---------------+
Пример 4. В строгом режиме, вставляя значение, которое испытывает недостаток диапазона для столбца, вызывает ошибку, а не усечение к юридическому значению.
Когда MySQL не работает в строгом режиме, усечение к юридическому значению происходит:
mysql>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)
Однако, ошибка происходит, если строгий режим в действительности:
mysql>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 1mysql>SELECT i FROM t;
Empty set (0.00 sec)
Пример 5: В строгом режиме и с ERROR_FOR_DIVISION_BY_ZERO
набор, подразделение нулем вызывает ошибку, не
результат NULL
.
В нестрогом режиме у подразделения нулем есть результат NULL
:
mysql>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 в действительности:
mysql>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 0mysql>SELECT i FROM t;
Empty set (0.01 sec)
Пример 6. Литералы точного значения оцениваются как точные значения.
До MySQL 5.0.3 точное значение и литералы приближенного значения оба оцениваются как двойная точность значения с плавающей точкой:
mysql>SELECT VERSION();
+------------+| VERSION() |+------------+| 4.1.18-log |+------------+1 row in set (0.01 sec)mysql>CREATE TABLE t SELECT 2.5 AS a, 25E-1 AS b;
Query OK, 1 row affected (0.07 sec)Records: 1 Duplicates: 0 Warnings: 0mysql>DESCRIBE t;
+-------+-------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+-------------+------+-----+---------+-------+| a | double(3,1) | | | 0.0 | || b | double | | | 0 | |+-------+-------------+------+-----+---------+-------+2 rows in set (0.04 sec)
С MySQL 5.0.3 литерал приближенного значения оценивается, используя плавающую точку, но литерал точного значения
обрабатывается как DECIMAL
:
mysql>SELECT VERSION();
+-----------------+| VERSION() |+-----------------+| 5.1.6-alpha-log |+-----------------+1 row in set (0.11 sec)mysql>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: 0mysql>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. Если параметром агрегатной функции является точный числовой тип, результатом является также точный числовой тип с масштабом, по крайней мере, тот из параметра.
Рассмотрите эти операторы:
mysql>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;
Перед MySQL 5.0.3 результатом является двойное независимо от того тип параметра:
mysql> DESCRIBE y;
+--------+--------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+--------+--------------+------+-----+---------+-------+| AVG(i) | double(17,4) | YES | | NULL | || AVG(d) | double(17,4) | YES | | NULL | || AVG(f) | double | YES | | NULL | |+--------+--------------+------+-----+---------+-------+
С MySQL 5.0.3 результатом является двойное только для параметра с плавающей точкой. Для точных параметров типа результатом является также точный тип:
mysql> 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 | |+--------+---------------+------+-----+---------+-------+
Результатом является двойное только для параметра с плавающей точкой. Для точных параметров типа результатом является также точный тип.