PDO准备不替换命名占位符

时间:2014-05-03 17:58:08

标签: php mysql pdo

我尝试使用命名占位符来填写数据,如下所示:

    $STH = $DBH->prepare("SELECT mixes.* FROM mixes JOIN(SELECT id FROM mixes WHERE id NOT IN ( :noredo_ids )  ORDER BY RAND() LIMIT 1) ips on mixes.id = ips.id"); 
    $STH->bindParam(':noredo_ids', $_GET["noredo"]);
    $STH->setFetchMode(PDO::FETCH_ASSOC); 
    $STH->execute();

除了尝试

    $arr2["ids"] = $_GET["noredo"];

    $STH = $DBH->prepare("SELECT mixes.* FROM mixes JOIN(SELECT id FROM mixes WHERE id NOT IN ( :ids )  ORDER BY RAND() LIMIT 1) ips on mixes.id = ips.id"); 
    $STH->setFetchMode(PDO::FETCH_ASSOC); 
    $STH->execute($arr2);

但这些都不起作用。但是当我尝试手动输入字符串而不是使用占位符时,它确实有效:

        $arr2["ids"] = $_GET["noredo"];

    $STH = $DBH->prepare("SELECT mixes.* FROM mixes JOIN(SELECT id FROM mixes WHERE id NOT IN (". $arr2['ids'] .")  ORDER BY RAND() LIMIT 1) ips on mixes.id = ips.id"); 
    $STH->setFetchMode(PDO::FETCH_ASSOC); 
    $STH->execute();

我应该手动逃脱字符串吗?我错过了一些明显的东西吗谢谢!

3 个答案:

答案 0 :(得分:0)

我不确定,因为PHP关于准备好的语句的命名占位符的文档对此有点模糊。 http://php.net/manual/en/pdostatement.bindparam.php

但如果$ _GET [' noredo']是一系列ID,您需要首先崩溃(',',$ _ GET [' noredo'] )在进入准备好的声明之前,我不认为占位符替换是否足够聪明,可以将数组压缩成可以在IN()中使用的逗号分隔列表。

在PHP文档中,替换是单个值而不是值数组,所以(这就是我模糊的地方)我不相信它会找到:数组中的named_placeholder你传了它。

但话说回来,我只使用了?准备好的陈述的占位符......

答案 1 :(得分:0)

查询参数始终取代SQL表达式中的单个标量值。

因此,如果您希望$_GET["noredo"]是数组或以逗号分隔的值列表,那么您所做的工作将无法完成。查询将像您执行此操作一样运行:

WHERE id NOT IN ( '1,2,3,4' )

包含以逗号分隔的列表的带引号的字符串值与一系列以逗号分隔的值不同。它是一个字符串,在数字上下文中,SQL将转换为' 1,2,3,4'进入标量数字1。

因此,如果要在IN()谓词中绑定多个值,则需要使用多个占位符。

$id_array = (array) $_GET["noredo"];

$placeholders = implode(",", array_fill(0,count($id_array),"?"));

$STH = $DBH->prepare("SELECT mixes.* FROM mixes JOIN(SELECT id FROM mixes 
    WHERE id NOT IN ( $placeholders )  ORDER BY RAND() LIMIT 1) ips on mixes.id = ips.id"); 

$STH->execute($id_array);

答案 2 :(得分:-1)

第二个例子不起作用,因为据我所知你使用了$arr2["ids"]而不是$arr2[":ids"]。也就是说,您仍然必须使用完整的参数名称。

此外,您应该确保您尝试插入的值已正确清理,并且不会导致语法错误。