如何在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,我可以轻松跳过准备好的语句:)