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


How to wrap correctly prepared statements and implement IN(?) expression with array binding?

我想使用这样的查询:

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

和bind数组

$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.

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

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

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

那是一个很有趣的问题,我花了一些时间来研究。

在朋友的帮助下进行了一些非常有趣的讨论后,我得出结论,如果数组为空,则将NULL传递到IN()语句中。它做出了非常明智的行为,并且不会使查询失败。

但是,还有一个问题没有解决:

虽然IN(NULL)返回FALSE,似乎相当明智,NOT IN(NULL)返回…假了!所以,你要小心这种说法。

对于我自己的实现,我使用条件查询构建作为解决方案,仅在非空数组的情况下添加整个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问题的建议。