MYSQL中使用PHP PDO进行NOT IN查询

5
我有一个名为$_POST ['excludeids'] 的 post 变量,其值为以下内容:
1,2,3,4,5,6,7,8,9

我希望通过 NOT IN 将此内容传递到 SQL 查询中,因此使用以下查询:
$STH = $DBH->prepare("SELECT * FROM books WHERE id NOT IN (:excludeids)");
$STH->bindValue(':excludeids', $_POST['excludeids']);
$STH->execute();

在这种情况下,绑定变量无法正常工作,我不知道原因。上述查询有什么问题吗?


SQL语句中缺少一个引号" - Mattiavelli
纠正了这个错误 :) - Michael Samuel
请查看此问题。https://dev59.com/VnNA5IYBdhLWcg3wh-gC - DevZer0
3个回答

9

因为IN()子句需要的是一个值的集合,而不是一个逗号分隔的字符串,所以它不能以这种方式工作。你试图将它们全部绑定为一个参数,但这并不可行。

要使其正常工作,你需要单独绑定集合中的每个元素:

// Split the IDs into an array
$ids = preg_split('/\s*,\s*/', $_POST['excludeids'], -1, PREG_SPLIT_NO_EMPTY);

// Create an array of ? characters the same length as the number of IDs and join
// it together with commas, so it can be used in the query string
$placeHolders = implode(', ', array_fill(0, count($ids), '?'));

// Prepare the statement
$STH = $DBH->prepare("SELECT * FROM books WHERE id NOT IN ($placeHolders)");

// Iterate the IDs and bind them
// Remember ? placeholders are 1-indexed!
foreach ($ids as $index => $value) {
    $STH->bindValue($index + 1, $value, PDO::PARAM_INT);
}

// This should now work
$STH->execute();

好的,问题解决了,但是又出现了另一个问题...为什么我要使用preg_split呢?当我尝试用$ids = array($_POST['excldeids'])替换你代码中的第一行时,查询没有返回任何结果...我尝试将字符串在jquery中发送为'1','2','3'而不是1,2,3,但仍然没有返回任何结果。 - Michael Samuel
1
因为 $_POST['excldeids'] 是一个逗号分隔的字符串。你需要将它转换成一个数组,每个逗号分隔的值作为一个元素。array($_POST['excldeids']) 只会创建一个只有一个元素的数组,即原始的逗号分隔字符串。 - DaveRandom
如果我使用JavaScript将ID作为数组推送,是否有一种方法可以直接在PHP中使用它,而不必使用preg_split? - Michael Samuel
如果您正在使用jQuery,它提供了一个名为jQuery.serializeArray()的帮助函数,它将为您创建一个正确格式化的字符串,以便您可以直接在PHP中使用。或者,您可以使用JSON.stringify()将参数作为JSON传递,然后在PHP中使用json_decode()进行解码。但归根结底,数据始终作为字符串传递到PHP中,您始终需要将其解码为数组-所有机制都非常相似。 - DaveRandom
只要您的输入字符串仅包含逗号和数字,explode() 就可以正常工作。我使用 preg_split() 的唯一原因是为了处理不需要的空格。@MichaelSamuel - DaveRandom
显示剩余4条评论

3

您需要循环遍历ID(首先将其分解为数组),并动态创建新参数,既可以在SQL字符串中,也可以使用bindValue


它们是字符串,不是数组,我认为。 - Royal Bg
我使用jQuery将其作为字符串传递。 - Michael Samuel
你能给我展示一个例子吗?因为我无法理解你的意思。谢谢 :) - Michael Samuel
我为您的参考发布了一个问题。请往上看。 - DevZer0
现在我面临另一个问题...我想使用 $STH->bindValue(':test', $_POST['test']); 绑定另一个变量,但是我得到了以下错误:无效的参数编号:混合命名和定位参数 - Michael Samuel

0
    $all_id = array(1, 2, 3, 4,5);
    $countArr = count($all_id);
    for($countArr; $countArr > 0; $countArr--)
        $in[]= '?';
    $in = implode(', ', $in);   
    $stmt = $dbh->prepare("
        SELECT ID
        FROM  b_iblock_element 
        WHERE  XML_ID NOT IN  ( ".$in.")
    ");
    if ($stmt->execute($all_id)) {
        while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            echo '<pre>'; print_r($row); echo'</pre>';
        }
    }
    $stmt->execute();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接