715988985123857 如何以及为什么变成 2147483647?
为什么没有被截断?
这种转换背后的机制是什么,可以用一些公式计算得到的数字吗?
该行为取决于 MySQL Strict SQL Mode设置:
严格模式控制 MySQL 如何处理数据更改语句(如 INSERT 或 UPDATE)中的无效或缺失值。
MySQL手册中有一章解释了MySQL如何处理超出范围的值:超出范围和溢出处理:
[...] 如果没有启用限制模式,MySQL 会将值剪辑到范围的适当端点并存储结果值。
在Integer Type的情况下,最大值为:
- 2147483647 用于签名类型
- 无符号类型为 4294967295
由于您的查询没有引发错误,而是使用最大允许值更新了该列,因此您可以假设您的服务器上未启用严格 SQL 模式。您可以通过运行来验证:
SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;
它们都不包含STRICT_TRANS_TABLES
norSTRICT_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"
...并基于此确定允许的限制。
非sql?数据验证(服务器端和客户端)是解决方案。