如何在PHP中使用带有in子句的查询中使用准备好的语句

如何在PHP中使用带有in子句的查询中使用准备好的语句,php,mysql,prepared-statement,Php,Mysql,Prepared Statement,我需要做一个简单的查询 $array_of_ids = array(); //poulate $array_of_ids, they don't come from another db but from Facebook //so i can't use a subquery for the IN clause $wpdb->prepare("SELECT id from table where id IN (%d, %d)", $array_of_ids [0], $array_of_

我需要做一个简单的查询

$array_of_ids = array();
//poulate $array_of_ids, they don't come from another db but from Facebook
//so i can't use a subquery for the IN clause
$wpdb->prepare("SELECT id from table where id IN (%d, %d)", $array_of_ids [0], $array_of_ids [1]);

问题是,如果数组中有200个元素,那么正确的处理方法是什么?是否必须使用200
%d
手动构建查询?我需要此查询,因为我必须将我的数据库与facebook数据“同步”,并且我必须检查数据库中的用户是否存在,更新存在的用户,插入新用户并删除非我朋友的用户。

如果您确定数组元素是数字的:

$wpdb->prepare("SELECT id FROM table WHERE id IN ("
  . implode(',',$array_of_ids) . ")");
否则,您可以使用
prepare
vsprintf
形式传入参数数组:

$wpdb->prepare("SELECT id FROM table WHERE id IN ("
  . str_repeat("%d,", count($array_of_ids)-1) . "%d)" , $array_of_ids);

是的,动态sql就是这样。幸运的是,整数很容易不出错

$vals = array_filter(array_map('intval', $vals));

确保至少有一个值,然后将其内爆。这里不需要准备语句,只需执行sql即可。

我不确定这是一种好方法,但您可以这样做:

$sql = "SELECT id from table where id IN (" 
     . implode(',', array_fill(0, count($array_of_ids), "%d"))
     . ")";

call_user_func_array(array($wpdb, 'prepare'), $array_of_ids);
这将生成一个具有适当数量的
%d
的字符串,然后使用
调用用户函数数组来动态执行此操作

也就是说,我不确定这是否真的是一个准备好的语句值得麻烦的情况,因为清理整数是多么容易。

您可以这样做:

$query = $wpdb->prepare("SELECT id from table where id IN :param");
$query->bindParam("param", "(".implode(',', array_map('intval', $array_of_ids)).")");

因为这还没有被接受的答案,所以我将继续我的方法

将输出

SELECT id from table where id IN (0,1,1,2,3,5,8,13)
SELECT id from table where id IN (1,2,3,5,8)

将输出

SELECT id from table where id IN (0,1,1,2,3,5,8,13)
SELECT id from table where id IN (1,2,3,5,8)

请注意,
is_int
不适用于$\u GET变量,因此使用
is_numeric
来代替

看看[这个问题][1]是否没有回答你的问题[1]:有点违背了准备语句的全部目的,是不是“tcha”。你可以做一个
内爆(',',数组映射('intval',$array\u of_id))
以确保它们实际上是数字。公平点数;我只是好奇,你为什么不做str\u repeat(“%d”),count($array\u of_id))。“”“
?有没有我遗漏的边缘案例?@JosephSilber:是的,那会有用的。。。但是几乎可以肯定的是,仅仅为了将其内容内爆为字符串而迭代构造数组的性能会降低…当然
array\u map('intval',…)
保证了SQL注入的安全性?在我看来,如果绑定
param
,它将被SQL转义、引用,并被当作一个字符串…而不是一个列表的东西。除非MySQL能够将字符串解释为列表,否则这可能不会起作用。$wpdb->prepare()实际上并不“准备”数据库中的语句,而只是清理参数。另外,您的$query->bindParam()调用将生成一个错误,因为$wpdb->prepare()返回一个字符串,而不是您的答案所返回的PDOStatement对象suggest@thorne51你的评论不清楚。这段代码是有效的,我不认为它会像你说的那样失败@赵:不是这样,您正在从ID的数组中创建一个列表,但是如果一个条目包含“,”,您的请求可能会失败。可能不是SQL注入,而是安全方面的工作。“intval”阻止了它。我认为array_map()很好地实现了这一点,但是如果以这种方式使用array map,我可以轻松跳过准备好的语句:)