Длинное целое число преобразуется при вставке в более короткий столбец, не обрезается. Зачем? Какая формула?
У меня есть столбец типа 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
?
Почему оно не обрезалось?
Каков механизм этого преобразования, и можно ли рассчитать полученное число по некоторой формуле?
Я не ищу решение. Я просто хочу понять конкретное число.
3 ответа
http://dev.mysql.com/doc/refman/5.0/en/integer-types.html
Целочисленное переполнение установит максимально допустимое число в БД как
2147483647
Так вам нужно bigint
тип данных для хранения большего целого числа
Как и почему 715988985123857 превратился в 2147483647?
Почему оно не обрезалось?
Каков механизм этого преобразования, и можно ли рассчитать полученное число по некоторой формуле?
Поведение зависит от настройки режима SQL строгого SQL:
Строгий режим контролирует, как MySQL обрабатывает недопустимые или отсутствующие значения в операторах изменения данных, таких как INSERT или UPDATE.
В руководстве MySQL есть глава, объясняющая, как MySQL обрабатывает значения вне диапазона: Обработка вне диапазона и Переполнение:
[...] Если никакие ограничительные режимы не включены, MySQL обрезает значение до соответствующей конечной точки диапазона и сохраняет полученное значение.
В случае целочисленного типа максимальное значение:
- 2147483647 для подписанного типа
- 4294967295 для беззнакового типа
Поскольку ваш запрос не выдал ошибку, а вместо этого столбец был обновлен с максимально допустимым значением, вы можете предположить, что строгий режим SQL не включен на вашем сервере. Вы можете проверить это, запустив:
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? Проверка данных (на стороне сервера и на стороне клиента) является решением.
Well as far as i know, it doesn't have anything to do with PHP, bcx.
- Если PHP встречает число за пределами целочисленного типа, оно будет интерпретироваться как число с плавающей точкой.
- Кроме того, операция, результатом которой является число, выходящее за пределы целочисленного типа, вместо этого вернет число с плавающей запятой.
So it will be the functionality of SQL which changes the value.