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