У меня есть столбец типа integer
с длиной 10:
`some_number` int(10) unsigned NOT NULL
В этот столбец я вставляю слишком длинный номер:
$some_number = 715988985123857; $query = "INSERT INTO this_table SET some_number = ?"; $stmt = $mysqli->prepare($query); $stmt->bind_param('i', $some_number); $stmt->execute();
Когда я смотрю, что находится в таблице, теперь число:
2147483647
Как и почему 715988985123857
превратился в 2147483647
?
Почему он не уселся?
Каков механизм этого преобразования, и может ли полученное число быть вычислено с помощью некоторой формулы?
Я не ищу решения. Я просто хочу понять конкретный номер.
http://dev.mysql.com/doc/refman/5.0/en/integer-types.html
Целочисленное переполнение задает максимальное допустимое число в БД как
2147483647
Таким образом, вам нужен bigint
данных bigint
для хранения большего целого числа
Как и почему 715988985123857отвернуться в 2147483647?
Почему он не уселся?
Каков механизм этого преобразования, и может ли полученное число быть вычислено с помощью некоторой формулы?
Поведение зависит от настройки MySQL Strict SQL Mode :
Строгий режим контролирует, как MySQL обрабатывает недопустимые или отсутствующие значения в операторах смены данных, таких как INSERT или UPDATE.
В руководстве MySQL есть глава, объясняющая, как MySQL обрабатывает значения вне диапазона: Обработка вне диапазона и переполнения :
[…] Если не разрешены ограничительные режимы, MySQL скопирует значение в соответствующую конечную точку диапазона и вместо этого сохранит результирующее значение.
В случае типа Integer максимальное значение:
Поскольку ваш запрос не выдавал ошибку, но вместо этого столбец обновлялся с максимально допустимым значением, вы можете предположить, что Strict SQL Mode не включен на вашем сервере. Вы можете проверить, выполнив:
SELECT @@GLOBAL.sql_mode; SELECT @@SESSION.sql_mode;
Ни один из них не будет содержать значения STRICT_TRANS_TABLES
или STRICT_ALL_TABLES
(подробнее о значениях в MySQL man: sql_mode
).
Возьмите этот пример, чтобы проверить различные типы поведения между режимами:
mysql> create table test_sql_mode(id int); mysql> set sql_mode = 'STRICT_TRANS_TABLES'; mysql> SELECT @@SESSION.sql_mode; +---------------------+ | @@SESSION.sql_mode | +---------------------+ | STRICT_TRANS_TABLES | +---------------------+ 1 row in set (0.00 sec) mysql> insert into test_sql_mode(id) value(123456789123456789); ERROR 1264 (22003): Out of range value for column 'id' at row 1 mysql> select * from test_sql_mode; Empty set (0.00 sec) mysql> set sql_mode = ''; mysql> SELECT @@SESSION.sql_mode; +--------------------+ | @@SESSION.sql_mode | +--------------------+ | | +--------------------+ 1 row in set (0.00 sec) mysql> insert into test_sql_mode(id) value(123456789123456789); Query OK, 1 row affected, 1 warning (0.05 sec) mysql> show warnings; +-------+------+---------------------------------------------+ | Level | Code | Message | +-------+------+---------------------------------------------+ | Error | 1264 | Out of range value for column 'id' at row 1 | +-------+------+---------------------------------------------+ mysql> select * from test_sql_mode; +------------+ | id | +------------+ | 2147483647 | +------------+ 1 row in set (0.00 sec)
Короче говоря, при строгом режиме вне диапазона значения выдает ошибку, без – значение корректируется до допустимого предела и выдается предупреждение.
Что касается этого вопроса:
может ли полученное число быть вычислено с помощью некоторой формулы?
Я не знаю простой и чистой формулы MySQL. Вам нужно будет проверить тип и длину данных:
select data_type, numeric_precision, numeric_scale from information_schema.columns where table_schema = "test_database" and table_name = "test_sql_mode" and column_name = "id"
… и на основе этого определяют допустимый предел.
Non-SQL? Валидация данных (серверная и клиентская) – это решение.
Ну, насколько я знаю, это не имеет ничего общего с PHP, bcx.
Таким образом, функциональность SQL изменит значение.