MySQL IN语句的PDO绑定值

我有一个与PDO有关的问题,我很想在被它困扰了一段时间之后得到答案。

以这个例子:

我将一个ID数组绑定到PDO语句以用于MySQL IN语句。

该数组将会说: $ values = array(1,2,3,4,5,6,7,8);

数据库安全变量应该是$ products = implode(','$ values);

因此, $产品将会是一个值为'1,2,3,4,5,6,7,8'的STRING

声明如下所示:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (:products)

当然, 美元产品将被视为:产品

但是,当语句被编译并绑定了值时,它实际上看起来像这样:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN ('1,2,3,4,5,6,7,8')

问题在于它将IN语句中的所有内容作为单个字符串执行,因为我已将它准备为逗号分隔值以绑定到语句。

我真正需要的是:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (1,2,3,4,5,6,7,8)

我实际上可以做到这一点的唯一方法是将这些值放入字符串本身而不绑定它们,但是我确定必须有一个更简单的方法来完成此操作。


这与在这个问题中提出的问题是一样的:我可以将数组绑定到IN()条件吗?

答案是,对于in子句中的可变大小列表,您需要自己构造查询。

但是,您可以通过使用引号,逗号分隔的列表find_in_set ,但对于大数据集,这将有相当大的性能影响,因为表中的每个值必须转换为char类型。

例如:

select users.id
from users
join products
on products.user_id = users.id
where find_in_set(cast(products.id as char), :products)

或者,作为第三种选择,您可以创建一个用户定义的函数,为您分割逗号分隔列表(参见http://www.slickdev.com/2008/09/15/mysql-query-real-values-从分隔符分隔的字符串的IDS /)。 这可能是三者中最好的选择,特别是如果你有很多依赖in(...)子句的查询。


处理这种情况的一个好方法是使用str_pad来放置一个? 为SQL查询中的每个值。 然后你可以传递值的数组(在你的情况下$values )作为参数执行:

$sql = '
SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products.id IN ('.str_pad('',count($values)*2-1,'?,').')
';

$sth = $dbh->prepare($sql);
$sth->execute($values);
$user_ids = $sth->fetchAll();

通过这种方式,您可以从使用预准备语句中获得更多好处,而不是直接将值插入到SQL中。

PS - 如果具有给定ID的产品共享用户ID,结果将返回重复的用户ID。 如果你只想要唯一的用户id,我建议将查询的第一行改为SELECT DISTINCT users.id


在这样的情况下,你可能想到的最好的准备就是类似下面的内容:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (?,?,?,?,?,?,?,?)

然后,您将循环访问您的值并将它们绑定到准备好的语句,确保问号的数量与绑定的值相同。

链接地址: http://www.djcxy.com/p/93655.html

上一篇: PDO binding values for MySQL IN statement

下一篇: how safe are PDO prepared statements