MySQL IN语句的PDO绑定值

hd8*_*d82 71 php mysql pdo sql-in

我有一个PDO的问题,我很想在被它困扰很长一段时间后得到答案.

举个例子:

我将一个ID数组绑定到PDO语句,以便在MySQL IN语句中使用.

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

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

因此,$ products将成为STRING,其值为:'1,2,3,4,5,6,7,8'

声明如下:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (:products)
Run Code Online (Sandbox Code Playgroud)

当然,$产品将被声明为:产品.

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

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

问题是它将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)
Run Code Online (Sandbox Code Playgroud)

我实际上可以实现这一点的唯一方法是将值放在字符串本身而不绑定它们,但我知道必须有一种更简单的方法来执行此操作.

Jam*_*lis 38

这与此问题中的问题相同: 我可以将数组绑定到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)
Run Code Online (Sandbox Code Playgroud)

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

  • Geez,PDO是一个如此简洁的库,但却错过了一些最基本的功能.有点遗憾...... (69认同)

ghb*_*att 27

处理这种情况的一种好方法是使用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();
Run Code Online (Sandbox Code Playgroud)

这样,您可以从使用预准备语句中获得更多好处,而不是将值直接插入SQL中.

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

  • 我更喜欢使用`implode(',',array_fill(1,count($ values),'?'))`因为逐个错误的可能性较小,而且你不必处理最后一个元素不同. (3认同)
  • 您也可以为此使用 str_repeat(),它可能是所列方法中最有效的:`rtrim( str_reapeat('?,', count($values)), ',')` (2认同)

Asa*_*aph 8

在这种情况下你可能想出的最准备好的陈述类似于以下内容:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (?,?,?,?,?,?,?,?)
Run Code Online (Sandbox Code Playgroud)

然后,您将遍历您的值并将它们绑定到预准备语句,确保与您绑定的值具有相同数量的问号.

  • 逻辑解决方案,当您知道要绑定多少变量但是当您有无限数量的参数时它会变得有点乱. (7认同)

小智 6

你需要在IN中提供相同数量的?s作为$ values数组中的值的数量

这可以通过创建一个?s数组来轻松完成

 $in = join(',', array_fill(0, count($values), '?'));
Run Code Online (Sandbox Code Playgroud)

并在IN子句中使用此$ in数组

这将动态地为您提供量身定制的阵列?的,按您的changiing $值数组