如何包装正确准备的语句并使用数组绑定实现IN(?)表达式?

时间:2013-03-30 16:18:01

标签: php mysql sql prepared-statement

我想使用这样的查询:

$sql = "SELECT `name` FROM `table` WHERE `id` IN (?)";

并绑定值数组

$sth = $pdo->prepare($sql);
$sth->execute(array(array('1', '2', '4')));

所以,我必须包装PDO。如何实现这种行为并考虑所有陷阱?

必须考虑:

IN(?) with array values;
IN(?) with empty array;
NOT IN(?) with array values;
NOT IN(?) with empty array;
NOT (expr IN (?)) with array values;
NOT (expr IN (?)) with empty.

问题变成我们有一个空数组。简单的我可以在这种情况下将通配符替换为null。但是,如果我没有(?)和空数组,我必须做什么?

热点是NOT IN (?)使用空数组。

1 个答案:

答案 0 :(得分:2)

  

问题就变成了我们有一个空数组。

这是一个非常有趣的问题,花了我一些时间来调查。

在我朋友的帮助下进行了一些非常有趣的辩论后,我得出结论是将NULL传递给IN()语句,以防数组为空。它会产生非常明智的行为,并且不会使查询失败。

然而,一个问题仍未解决:

虽然IN(NULL)返回FALSE并且看起来很合理,NOT IN(NULL)会再次返回... FALSE!所以,你必须小心这种说法。

对于我自己的实现,我使用条件查询构建作为一种解决方法,仅在非空数组的情况下添加整个NOT IN()语句。它使逻辑稳固,但代价是额外的代码:

$in = '';
if ($array) {
    $in = $db->parse(" AND col NOT IN(?a)", $array);
}
$data = $db->getAll("SELECT * FROM t WHERE name=?s ?p", $name, $in);

(在直接IN的情况下将其与简明陈述进行比较):

$data = $db->getAll("SELECT * FROM t WHERE name=?s AND col IN(?a)", $name, $in);

如果数组为空,则不返回任何行。

所以,我仍然愿意接受有关如何更优雅地解决NOT IN问题的建议。