【发布时间】:2011-11-01 17:37:56
【问题描述】:
我有一个包含多个 id 的数组,我需要更新多个列。我为此使用 MySQL IN()。问题是当我使用下面的查询时它工作得很好。
public function available($value, $propertyId = array()) {
$sth = $this->dbh->prepare('UPDATE properties p SET p.status = :status WHERE p.id IN('.implode(',',$propertyId).')');
$sth->bindParam(':status',$value);
return $sth->execute();
}
由于上述查询没有为第二个参数$propertyId 使用任何占位符,我认为这样做是错误的方法。但是当我在查询中使用命名或未命名的占位符时,它只会更新 1 行。例如下面的代码只更新一行。
//This will update only one row.
//Using Named Place Holder
public function available($value, $propertyId = array()) {
$sth = $this->dbh->prepare('UPDATE properties p SET p.status = :status WHERE p.id IN(:propertyId)');
$sth->bindParam(':status',$value);
$sth->bindParam(':propertyId', implode(',', $propertyId));
return $sth->execute();
}
或者
//Using Unnamed Place Holder.
public function available($value, $propertyId = array()) {
$sth = $this->dbh->prepare('UPDATE properties p SET p.status = ? WHERE p.id IN(?)');
return $sth->execute(array($value, implode(',', $propertyId)));
}
我尝试将数组转换为字符串并将其分配给如下变量。
public function available($value, $propertyId = array()) {
$id = implode(',', $propertyId);
$sth = $this->dbh->prepare('UPDATE properties p SET p.status = ? WHERE p.id IN(?)');
return $sth->execute(array($value, $id));
}
即使这样也行不通。怎么了?我错过了什么?
谢谢
【问题讨论】:
-
AFAIK 参数化查询不能与列表
IN (...)一起使用,如果您没有使用占位符指定每个元素。IN (?,?,?,? ...)。当 propertyId 仅包含整数值时,您的第一个查询就是要走的路。 -
您可以在stackoverflow.com/questions/327274/…找到类似问题的解决方案
-
只是为了支持第一条评论,
DoctrineORM 使用PDO并为IN查询生成(?,?,?,....)。 -
@culrais,第一个查询对 SQL 注入安全吗?我不知道,但我认为那样做是不安全的。
-
@Ibrahim Azhar Armar,使用php.net/manual/en/pdo.quote.php 转义您在该查询中传递的所有数据(数组中的每个值,而不是内爆字符串),您将与使用 pdo::prepare/bind_param 一样安全, 但当然会产生更多的流量到 SQL 服务器 - 每个 eascape 调用都应该是 MySql 调用。