绑定 IN 运算符的 PDO 问题


PDO issues with binding IN operator

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

$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

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

每个 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 转换为带引号的字符串,尤其是您有一个大型数据库、复杂的查询和更喜欢整数。