【问题标题】:PHP int being converted to different string by MySQLPHP int 被 MySQL 转换为不同的字符串
【发布时间】:2015-12-28 02:29:41
【问题描述】:

我在 Magento 脚本中有这段代码:

$order = $observer->getEvent()->getOrder();
$customer_id = $order->getBillingAddress()->getCustomerId();

$idArray = array('LN123456789XZY'); // this is just arbitray sample data, the array can be any length

$prequery = "UPDATE $detailedTable SET ordered=1 WHERE customer_id=$customer_id AND image_id IN (";
$qPart = array_fill(0, count($idArray), "?");
$prequery .= implode(",", $qPart) . ")";
$query = $dbLink->prepare($prequery);
$i = 1;
foreach($idArray as $elem){
        $query->bindValue($i++, (string) $elem, PDO::PARAM_STR);                
}
$query->execute();

我看到的是$customer_id 的值正在被转换为具有完全不同值的字符串。我的表中这两列的数据类型是:

customer_id => VARCHAR(64)
image_id => TEXT

所以我意识到我的第一个问题是我没有用单引号包围$customer_id。但是发生了什么,因为它是一个 int 值,如 PHP 中的 1011,当它被写入 MySQL 时,它被转换为 'g-608311' 之类的东西。而且它会间歇性地发生。

所以当我在思考如何清理我的表中的东西时,我很好奇当数据类型不匹配时 MySQL 是如何从 int 1011 中得出那个“g-608311”字符串的?

编辑:我更新了代码 sn-p 以显示 $customer_id 值的实际来源。另外,我今天早些时候在思考这个问题时想到了这个,但是当我最初运行这段代码时,我得到了一个异常消息:

message SQLSTATE[22007]: Invalid datetime format: 1292 Truncated incorrect DOUBLE value: 'g-608311' 

【问题讨论】:

  • 周围的单引号不是强制性的。并且必须有其他东西(在 PHP 中!)导致 $customer_id 被覆盖。请显示更多代码。 (不要提供伪代码或为我们思考,已经填写了实际来自其他地方/功能的值)
  • 不确定是否重要,但我在代码 sn-p 中分配给 $customer_id 的值是 Xdebug 向我显示的值,即当我到达这段代码时的值。但是当我早上到达我的工作计算机时,我会发布更多代码。

标签: php mysql sql database


【解决方案1】:

虽然我不能确切地告诉你为什么由于你的未引用的字符串输入而得到不同的值,但我可以指出使用准备好的语句是多么荒谬......然后直接在查询中嵌入变量。

您的查询应该是:

$prequery = "UPDATE `literal_table_name_here` SET `ordered`=1
   WHERE `customer_id` = ?
   AND `image_id` IN (".str_repeat("?,",count($idArray)-1)."?)";
$query = $dbLink->prepare($prequery);
$query->bindValue(1,$customer_id);
foreach($idArray as $i=>$elem) {
   $query->bindValue($i+2, $elem, PDO_PARAM_STR);
}
$query->execute();

【讨论】:

  • 虽然你说的是真的,但这不是问题的答案。也没有解决问题的办法。
  • 所以我可以更好地学习/理解成为一个更好的程序员,但是为什么在字符串中使用变量然后将结果传递到准备好的语句中?我设想作为一个例子,我想要这样做就像我有一个用于与数据库交谈的通用类,并且我将表名作为变量传递,这样我就不能只是硬-将其编码。是否存在不良的编码习惯/安全问题/其他使其不好的原因?
  • @MikeLevy 传入一个在 constant 中定义的表名就可以了,但是对于像 customer_id 这样的值,你有点违背了准备好的语句的目的只需将其注入,您就会发现这样做会导致问题!
  • @NiettheDarkAbsol 我测试了你的解决方案,它看起来已经解决了这个问题。我仍然不能 100% 确定“为什么”部分,但现在我知道“在哪里”,所以我对此很满意。珍惜洞察力!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-24
  • 1970-01-01
  • 2019-08-30
  • 2011-11-26
相关资源
最近更新 更多