使用MySQL" IN"正确绑定参数的方法Yii2中的语法?

时间:2015-05-02 09:03:51

标签: php mysql yii yii2

好的,我使用Yii2并且熟悉使用mysql查询时准备/绑定数据,例如:

$sql = $this->db->createCommand("UPDATE some_table SET something='foo' WHERE some_id=:some_id");
$sql->bindValue(':some_id', $some_id);

但是当包含多个值时,例如使用MySQL语法IN时会怎样?

例如:

$sql = $this->db->createCommand("UPDATE some_table SET something='foo' WHERE some_id IN (:parents)");
$sql->bindValue(':parents', $parents);

现在据我所知,如果$parents var只有一个值,上述情况才会有效;但如果它有多个值,例如1,2,3,那么当您真正想要'1,2,3''1','2','3'时,最终会得到类似1,2,3的内容。

这样做的正确方法是什么?

7 个答案:

答案 0 :(得分:6)

您可以使用Yii的QueryBuilder功能,一切都将自动处理。试试这个:

$params = [];
$sql = \Yii::$app->db->getQueryBuilder()->update('some_table', ['something' => 'foo'], ['some_id' => [1, 2, 3]], $params);

结果:

string(78) "UPDATE `some_table` SET `something`=:qp0 WHERE `some_id` IN (:qp1, :qp2, :qp3)"
array(4) { [":qp0"]=> string(3) "foo" [":qp1"]=> int(1) [":qp2"]=> int(2) [":qp3"]=> int(3) } 

答案 1 :(得分:4)

我找到了这个解决方案

$params = [];
$sql = \Yii::$app->db->getQueryBuilder()->buildCondition(['IN', 'some_id', $ids], $params);
//$sql = some_id NOT IN (:qp0, :qp1, :qp2)
//$params = [':qp0'=>1, ':qp1'=>2, ':qp2'=>3]
$this->db->createCommand("UPDATE some_table SET something='foo' WHERE $sql", $params);

答案 2 :(得分:3)

Yii2的数据库功能基于PDO。 根据{{​​3}}的手册,Array类型不支持价值。 (第三个参数 - data_type)。

解决方案是在查询之前创建一个字符串,该字符串适合您的IN子句并将其绑定为字符串。

类似的东西:

$parents = "1,2,3";
/*
Or in case you already have an array of the desirable ids:
$parents_array = array(1,2,3);
$parents = implode(",",$parents_array);
*/

$sql = $this->db->createCommand("UPDATE some_table SET something='foo' WHERE some_id IN (:parents)");
$sql->bindValue(':parents', $parents); 

修改

似乎占位符被内嵌数组替换为一个字符串值'1,2,3'而不是'1','2','3'(因为它是一个占位符)。

为了解决这个问题,我建议使用多个?占位符。 因此,IN (:parents)不是IN (?, ?, ?, ? ,....),而是因为我们已经有一个排列数组 - 我们可以使用count($array)来了解我们需要放置多少占位符。

//$parents = array(1,2,3);
$placeholders = str_repeat('?,', count($parents) - 1). '?';
$sql = $this->db->createCommand("UPDATE some_table SET something='foo' WHERE some_id IN (".$placeholders.")");

foreach($parents as $i => $parent){
 $sql->bindValue($i+1, $parent);  
}

请注意bindValue第一个参数的传递值; 这是手册中提到的$i+1而不是$i的原因:

  

对于使用问号占位符的预备声明,这将是   是参数的 1索引位置

有关更多信息和替代解决方案,请查看以下答案: bindValue

答案 3 :(得分:0)

我最终这样做了:

$parents_safe = '';
$parents_sep = explode(',', $parents);

foreach ($parents_sep as $parent) {
    $parents_safe .= $this->db->quoteValue($parent) . ',';
}

$parents_safe = rtrim($parents_safe, ',');

其中$this->dbYii::$app->db的实例。

答案 4 :(得分:0)

如果数据 TRUSTED ,这个解决方案效果很好:

$db = Yii::$app->db;
$ids = "'" . implode("','", $ids_array) . "'";
$result = $db->createCommand("
    UPDATE some_table SET something='foo' WHERE some_id IN ($ids)
")->queryColumn();

答案 5 :(得分:0)

如果某人需要 Yii1 的解决方案:

$db = \Yii::app()->db;

$inCondition = $db
    ->getCommandBuilder()
    ->createInCondition('some_table', 'some_id', $parents);

$command = $db
    ->createCommand("UPDATE some_table SET something = :foo WHERE $inCondition");

$command->bindValue(':foo', 'foo');
$command->execute();

答案 6 :(得分:-3)

只做

$parents = implode("','", $parrent_array);
$sql->bindValue(':parents', $parents);

应该可以做到这一点。