0

当我尝试使用 0123456789 进行更新时,MySQL 更新似乎使用 2147483647 的幻数进行了更新。

在某个地方,MySQL 似乎在任何模式的 INT 列上将一个数字与另一个数字相关联。我什至在哪里寻找这样的关联。详情如下。


此更新执行了预期的操作,并将 012345678 输入到相应行的 ContactPhone2 列中。

UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='012345678' WHERE `CustomerID`='cust-000004' and`ContactID`='1'

此更新实际上在相应行的 ContactPhone2 列中输入 2147483647;远离 0123456789。

UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='0123456789' WHERE `CustomerID`='cust-000004' and`ContactID`='1'

ContactPhone2 的数据类型是 INT(10),默认值为 NULL,并且没有设置参数(OK、NN、AI 等) 这是来自 MYSQL 常规日志。对于 012345678 更新。

 130101 17:51:43       89 Query set autocommit=0
 130101 17:51:44       89 Prepare   UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='012345678' WHERE `CustomerID`='cust-000004' and`ContactID`='1'
       89 Execute   UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='012345678' WHERE `CustomerID`='cust-000004' and`ContactID`='1'
       89 Query commit
       89 Close stmt

以及 0123456789 更新的日志条目。

130101 17:51:48    89 Query set autocommit=0
130101 17:51:49    89 Prepare   UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='0123456789' WHERE `CustomerID`='cust-000004' and`ContactID`='1'
       89 Execute   UPDATE `alacarte`.`customercontacts` SET `ContactPhone2`='0123456789' WHERE `CustomerID`='cust-000004' and`ContactID`='1'
       89 Query commit
       89 Close stmt

更新 0123456780 Works,所以它不是数字的长度。

这发生在整个数据库中具有 INT(10+) 的任何列上,但不会发生在 VARCHAR 列上。

更好的是,它在另一个名为thedesignge的模式上做同样的事情,该模式是旧模式,后来被复制和重命名,但它在 mysql 中仍然有效,尽管未使用。

列上没有运行任何触发器,并且只有一个触发器在 ContactID 列上的表上运行。也没有给出错误。

查询一般都是通过 MySQL 工作台进行的,虽然我试过一次在终端直接通过 shell 进入更新查询,得到了相同的结果。

在某个地方,MySQL 似乎在任何模式的 INT 列上将一个数字与另一个数字相关联。我什至在哪里寻找这样的关联。

我们还没有对缓存或索引做任何事情,除了 MySQL 默认的。我们正在运行 mysql 5.5.29

4

3 回答 3

2

2147483647 的“神奇”数字是 2^31-1,这是 int 的上限。这意味着它认为您输入的数字太大。

最好的选择是使用 varchar 来存储您的电话号码。确保它足够大以处理所有预期的情况,我强烈建议使用正则表达式格式化电话号码,以便为您清理输入。如果您只需要 (xxx) xxx-xxxx 而不需要扩展名或任何有趣的东西(如国际号码),这是一种在 php 中格式化电话号码的简单方法。

$phoneNumber = '1-(235) 555.1234';

$formatted = '';
if (preg_match('/1?[^0-9]*([02-9][0-9][0-9])[^0-9]*([0-9]{3})[^0-9]*([0-9]{4})/', $phoneNumber, $matches)) {
    $formatted = "($matches[1]) $matches[2]-$matches[3]";
} else {
    // phone number is invalid
}

结果将是 $formatted = (235) 555-1234。正则表达式包含一个可选的 1 前缀,该前缀被丢弃,并且第一个实际数字不能为 1。

显然,如果您使用它来格式化它,您应该在接受它之前使用相同的正则表达式来验证电话号码。

于 2013-01-02T02:12:35.093 回答
2

你可能溢出了你的 INT 值。当 MySQL 溢出时,默认情况下它存储数据类型支持的最大值。有符号 32 位整数的最大值是 2 31 -1,即 2147483647。

值“012345678”和“0123456789”是可以的。也就是说,它们在 INT 的范围内,并且它们插入得很好。所以我怀疑这些价值观是否真的造成了麻烦。

我会寻找其他一些使用超出范围的不同值进行更新的 SQL 语句。例如,有人可能试图通过电话分机添加他们的电话号码。

您可以启用严格模式,以便整数溢出导致错误,而不是静默截断值。当它发生时,它会更清楚地告诉你。

SET SQL_MODE='STRICT_ALL_TABLES';

http://dev.mysql.com/doc/refman/5.5/en/server-sql-mode.html

PS:您提到 INT(10) 好像整数参数对数据类型支持的值范围很重要。这是一个常见的误解,但没关系。INT 始终为 32 位。请参阅INT(10) 和 INT(12) 之间有什么区别(应用于我的代码时)?

于 2013-01-02T02:14:55.487 回答
1

你用的是什么mysql版本?我不能复制那个。

set ContactPhone2=round('0123456789')帮助吗?(假设你想保持前导零,只是改为 varchar 更好。)

于 2013-01-02T02:04:42.597 回答