Spec-Zone.ru › MySQL 5.7

11.1.7 Обработка значений вне диапазона и переполнения

При хранении MySQL значения в числовом столбце, выходящего за допустимый диапазон типа данных столбца, результат зависит от режима SQL, действующего в данный момент:

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

  • Если не включены режимы с ограничениями, 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 операторов. В режиме строгого SQL эти операторы завершаются ошибкой, и некоторые или все значения не вставляются или не изменяются, в зависимости от того, является ли таблица транзакционной таблицей и других факторов. Подробности см. в Разделе 5.1.10, «Режимы 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 |
+-------------------------------------------+

Происходит ли переполнение, зависит от диапазона операндов, поэтому другой способ обработки предыдущего выражения — использование точной арифметики, так как DECIMAL значения имеют больший диапазон, чем целые числа:

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

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

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)'

Если включён режим SQL NO_UNSIGNED_SUBTRACTION, результат будет отрицательным:

mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
|                      -1 |
+-------------------------+

Если результат такой операции используется для обновления столбца UNSIGNED со знаком, результат обрезается до максимального значения для типа столбца или обрезается до 0, если включён NO_UNSIGNED_SUBTRACTION. Если включён режим строгого SQL, возникает ошибка, и столбец остаётся неизменным.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/out-of-range-and-overflow.html

Spec-Zone.ru

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