绑定IN运算符

时间:2016-02-11 06:32:40

标签: php mysql pdo

  

注意:我认为这个问题可能是PDO驱动程序中的严重问题。我几乎可以理解数组和字符串之间的区别。因此,请在删除 duplicate 之前考虑在沙盒上对此进行测试。

$pdo = db()->getInstance();

$sql = "SELECT * FROM clients WHERE client_id IN :clients";
$params = [ ":clients" =>  "(223,224,225)" ];    

$stmt = $pdo->prepare($sql);
try{
    $stmt->execute($params);
} catch( \Exception $e){
    die("Query Execution Failed" . $e->getMessage());
}
  

查询执行失败SQLSTATE [42000]:语法错误或访问   违规:1064您的SQL语法有错误;检查手册   对应于您的MySQL服务器版本,以获得正确的语法   在第1行''(223,224,225)'附近使用

这里的问题不是转换为:

SELECT * FROM clients WHERE client_id IN (223,224,225)

它正在翻译为:

 SELECT * FROM clients WHERE client_id IN '(223,224,225)'

这里没有数组。我只是提供一个参数客户端来替换:clients为什么要添加quotes

1 个答案:

答案 0 :(得分:0)

首先,我(有点)同意你的看法。这是一个问题,不是很严重的问题。也许他们故意保留它。或者,也许你的愚蠢问题有一些争论的潜力。

  

每个PDO参数都包含引号。 (我个人认为不应该这样)。当您一次传递IN字符串时,它会在其周围放置引号,但查询失败。但是,您可以使用单个项目(放置引号)。因此,将参数传递给每个项目,而不是之前准备字符串。

现在,解决方案:

$pdo = db()->getInstance();

$sql = "SELECT * FROM clients WHERE client_id IN :clients";

$clients = [223,224,225];

/* You could use bind with ? here. I am just making this with named parameters so that you could echo SQL */

$params = [];
$replacement = [];

foreach ($clients as $key => $value){
    $replacement[] = ":client$key";
    $params[":client" . $key] = $value;
}
$sql = str_replace(":clients", "("  . implode(",",$replacement) . ")", $sql);

echo $sql;
/* SELECT * FROM clients WHERE client_id IN (:client0,:client1,:client2) */

$stmt = $pdo->prepare($sql);
try{
    $stmt->execute($params);
    print_pre($stmt->fetchAll(PDO::FETCH_ASSOC));
} catch( \Exception $e){
    die("Query Execution Failed" . $e->getMessage());
}

这就像一个魅力。我尝试创建一个虚拟客户端表。但问题是你的实际SQL现在变成了:

SELECT * FROM clients WHERE client_id IN ('223','224','225')

大多数人可能不会对此大肆宣传,但您可能会失去一些性能,因为查询将id转换为带引号的字符串,尤其是您拥有大型数据库,复杂查询和首选整数。