给定一个ids数组$galleries = array(1,2,5),我想有一个SQL查询,在它的WHERE子句中使用数组的值,如:

SELECT *
FROM galleries
WHERE id = /* values of array $galleries... eg. (1 || 2 || 5) */

我如何生成这个查询字符串与MySQL使用?


当前回答

下面是我使用的方法,对其他数据使用带有命名占位符的PDO。为了克服SQL注入,我过滤了数组,只接受整数的值,并拒绝所有其他的值。

$owner_id = 123;
$galleries = array(1,2,5,'abc');

$good_galleries = array_filter($chapter_arr, 'is_numeric');

$sql = "SELECT * FROM galleries WHERE owner=:OWNER_ID AND id IN ($good_galleries)";
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
    "OWNER_ID" => $owner_id,
));

$data = $stmt->fetchAll(PDO::FETCH_ASSOC);

其他回答

无PDO的安全方法:

$ids = array_filter(array_unique(array_map('intval', (array)$ids)));

if ($ids) {
    $query = 'SELECT * FROM `galleries` WHERE `id` IN ('.implode(',', $ids).');';
}

将$ids变量强制转换为数组 将所有数组值转换为整数 移除重复的值 删除零值 内爆连接所有值到IN选择

小心!此答案包含一个严重的SQL注入漏洞。不要使用这里给出的代码示例,除非确保任何外部输入都被清除。

$ids = join("','",$galleries);   
$sql = "SELECT * FROM galleries WHERE id IN ('$ids')";

因为最初的问题涉及到一个数字数组,而我使用的是一个字符串数组,我无法使给定的例子工作。

我发现每个字符串都需要封装在单引号中才能使用in()函数。

这是我的解决方案

foreach($status as $status_a) {
        $status_sql[] = '\''.$status_a.'\'';
    }
    $status = implode(',',$status_sql);

$sql = mysql_query("SELECT * FROM table WHERE id IN ($status)");

正如您所看到的,第一个函数用单引号(\')包装每个数组变量,然后内爆数组。

注意:$status在SQL语句中没有单引号。

可能有更好的方式添加引号,但这是可行的。

如果正确筛选输入数组,我们可以使用这个"WHERE id IN"子句。就像这样:

$galleries = array();

foreach ($_REQUEST['gallery_id'] as $key => $val) {
    $galleries[$key] = filter_var($val, FILTER_SANITIZE_NUMBER_INT);
}

如下面的例子所示:

$galleryIds = implode(',', $galleries);

也就是说,现在你应该安全地使用$query = "SELECT * FROM galleries WHERE id IN ({$galleryIds})";

除了使用IN查询,您还有两个选择,因为在IN查询中存在SQL注入漏洞的风险。您可以使用循环来获得所需的确切数据,也可以使用带有or大小写的查询

1. SELECT *
      FROM galleries WHERE id=1 or id=2 or id=5;


2. $ids = array(1, 2, 5);
   foreach ($ids as $id) {
      $data[] = SELECT *
                    FROM galleries WHERE id= $id;
   }