Php “从id位于()的用户中选择*”==失败

Php “从id位于()的用户中选择*”==失败,php,mysql,Php,Mysql,我有一个名为sqlf的函数,它模拟准备好的语句。例如,我可以做以下事情: $sql = sqlf("SELECT * FROM Users WHERE name= :1 AND email= :2",'Big "John"','bj@example.com') ; 出于各种原因,我不能使用预先准备好的语句,但我想模仿它们。我遇到的问题是这样的查询 $sql = sqlf("SELECT * FROM Users WHERE id IN (:1)",array(1,2,3) ); 我的代码可以工作

我有一个名为sqlf的函数,它模拟准备好的语句。例如,我可以做以下事情:

$sql = sqlf("SELECT * FROM Users WHERE name= :1 AND email= :2",'Big "John"','bj@example.com') ; 出于各种原因,我不能使用预先准备好的语句,但我想模仿它们。我遇到的问题是这样的查询

$sql = sqlf("SELECT * FROM Users WHERE id IN (:1)",array(1,2,3) ); 我的代码可以工作,但在空数组中失败,例如,下面抛出一个mysql错误:

SELECT * FROM Users WHERE id IN ();
有人有什么建议吗?我应该如何将空数组转换为可以注入IN子句的sql?替换NULL将不起作用

Null是唯一可以保证不在集合中的值。为什么这不是一个选择?其他任何内容都可以看作是潜在集合的一部分,它们都是值。

是否有可能使用sqlf检测空数组,并将SQL更改为不包含IN子句

或者,您可以在将SQL传递给真正的SQL执行器之前对其进行后处理,以便删除部分中的内容,尽管您必须做各种各样的欺骗来查看必须删除哪些其他元素,以便:

SELECT * FROM Users WHERE id IN ();
SELECT * FROM Users WHERE a = 7 AND id IN ();
SELECT * FROM Users WHERE id IN () OR a = 9;
将成为:

SELECT * FROM Users;
SELECT * FROM Users WHERE a = 7;
SELECT * FROM Users WHERE a = 9;

这可能会变得棘手,这取决于SQL的复杂性-您基本上需要一个完整的SQL语言解释器。

我唯一能想到的方法是让您的sqlf函数扫描,查看特定的替换是否在IN之后很快出现,然后查看传递的变量是否为空数组,输入一些你肯定不在该列的内容:例如,m,znmzcb~~1。这是一个黑客,当然,但它会工作


如果你想更进一步,你能改变你的函数,让它有不同类型的替换吗?它看起来像是你的函数扫描一个冒号,后跟一个数字。为什么不添加另一个类型,比如@后跟数字,这对于空数组是明智的,这样就不用扫描和猜测变量是否应该是数组。

如果您的prepare-like函数只是用等效参数替换:1,您可以尝试让您的查询包含如下内容:1',因此,如果:1为空,它将解析为,这不会导致解析错误,但是如果该字段可以有空值,它可能会导致不希望的行为-尽管如果它是int,这不是问题。但是,这不是一个非常干净的解决方案,最好检测数组是否为空,并简单地使用缺少IN:1组件的查询的替代版本。如果这是WHERE子句中的唯一逻辑,那么您可能不想选择所有内容,因此您不会执行查询。

我认为将空数组作为in子句的参数传递是一个错误。调用此函数时,您可以控制查询的语法,因此您还应该负责输入。我建议在调用函数之前检查参数是否为空。

我将使用零,假设您的id列是自动分配数字的伪密钥

据我所知,在大多数品牌的数据库中,自动密钥生成器从1开始。这是一种约定,而不是要求在标准SQL中未定义自动编号字段。但是这个惯例很普遍,你可以信赖它


因为零可能永远不会出现在id列中,所以当输入数组为空时,您可以在in谓词中使用此值,它将永远不会匹配。

我刚刚尝试过,它实际上是有效的。在NULL中,我认为会做与IS NULL相同的事情,但它们是不同的。谢谢你的回答。