Spec-Zone.ru › MySQL 5.7

12.21.3 Обработка выражений

При работе с точной математикой в качестве исходных данных, по возможности, используются числа с точным значением. Например, числа в сравнениях используются точно, как задано, без изменения значения. В строгом режиме SQL, для INSERT в столбец с точным типом данных (DECIMAL или целым), число вставляется со своим точным значением, если оно находится в диапазоне столбца. При извлечении значение должно быть таким же, как при вставке. (Если строгий режим SQL не включён, усечение для INSERT допустимо.)

Обработка числового выражения зависит от типа значений, содержащихся в выражении:

  • Если присутствуют приближённые значения, выражение приближённое и вычисляется с использованием арифметики с плавающей запятой.

  • Если приближённых значений нет, выражение содержит только точные значения. Если какое-либо точное значение содержит дробную часть (значение после десятичной точки), выражение вычисляется с использованием точной арифметики DECIMAL и имеет точность 65 цифр. Термин “точное” подчиняется ограничениям того, что может быть представлено в двоичном формате. Например, 1.0/3.0 может быть приближён в десятичной записи как .333..., но не записано как точное число, поэтому (1.0/3.0)*3.0 не вычисляется точно как 1.0.

  • В противном случае выражение содержит только целые значения. Выражение точно и вычисляется с использованием целочисленной арифметики и имеет точность, аналогичную BIGINT (64 бита).

Если числовое выражение содержит какие-либо строки, они преобразуются в значения двойной точности с плавающей запятой, и выражение является приближённым.

Вставки в числовые столбцы влияют на режим SQL, который контролируется переменной системы sql_mode. (См. Раздел 5.1.10, «Серверные режимы SQL».) В следующем обсуждении упоминается строгий режим (выбранный значениями режима STRICT_ALL_TABLES или STRICT_TRANS_TABLES) и ERROR_FOR_DIVISION_BY_ZERO. Чтобы включить все ограничения, можно просто использовать режим TRADITIONAL, который включает в себя как значения строгого режима, так и ERROR_FOR_DIVISION_BY_ZERO:

SET sql_mode='TRADITIONAL';

Если число вставляется в столбец точного типа (DECIMAL или целое), оно вставляется со своим точным значением, если оно находится в диапазоне и точности столбца.

Если значение имеет слишком много цифр в дробной части, происходит округление, и генерируется заметка. Округление выполняется, как описано в Разделе 12.21.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)

Подпоток не обнаруживается, поэтому обработка подпотока не определена.

Для вставок строк в числовые столбцы преобразование из строки в число обрабатывается следующим образом, если строка содержит нечисловые элементы:

  • Строка, не начинающаяся с цифры, не может быть использована как число и вызывает ошибку в строгом режиме или предупреждение в противном случае. Это включает в себя пустую строку.

  • Строка, начинающаяся с цифры, может быть преобразована, но хвостовая нечисловая часть усекается. Если усечённая часть содержит что-либо кроме пробелов, это вызывает ошибку в строгом режиме или предупреждение в противном случае.

По умолчанию деление на ноль даёт результат NULL и без предупреждения. Установив режим SQL соответствующим образом, можно ограничить деление на ноль.

При включении режима SQL ERROR_FOR_DIVISION_BY_ZERO, MySQL по-другому обрабатывает деление на ноль:

  • Если строгий режим не включён, появляется предупреждение.

  • Если строгий режим включён, вставки и обновления, включающие деление на ноль, запрещены, и возникает ошибка.

Другими словами, вставки и обновления, включающие выражения, выполняющие деление на ноль, могут рассматриваться как ошибки, но это требует ERROR_FOR_DIVISION_BY_ZERO в дополнение к строгому режиму.

Предположим, что у нас есть такое утверждение:

INSERT INTO t SET i = 1/0;

Вот что происходит для комбинаций режимов strict и ERROR_FOR_DIVISION_BY_ZERO.

Значение sql_mode Результат
'' (По умолчанию) Без предупреждения, без ошибки; i установлено в NULL.
strict Без предупреждения, без ошибки; i установлено в NULL.
ERROR_FOR_DIVISION_BY_ZERO Предупреждение, без ошибки; i установлено в NULL.
strict,ERROR_FOR_DIVISION_BY_ZERO Состояние ошибки; строка не вставляется.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/precision-math-expressions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API