“SELECT * FROM users WHERE id IN()”== FAIL

时间:2008-09-23 23:51:14

标签: 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) );

我的代码有效,但它失败了空数组,例如抛出一个mysql错误:

SELECT * FROM Users WHERE id IN ();

有没有人有任何建议?我应该如何将数组转换为可以注入IN子句的sql?替换NULL将不起作用。

6 个答案:

答案 0 :(得分:7)

Null是唯一可以保证不在集合中的值。怎么不是一个选择?任何其他东西都可以被视为潜在集合的一部分,它们都是价值观。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

另外,您可以在将SQL传递给“真正的”SQL执行器之前对其进行后处理,以便删除“IN()”部分,尽管您必须执行各种技巧以查看必须删除的其他元素这样:

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语言解释器。

答案 3 :(得分:0)

如果你的类似prepare的函数只是用等效参数替换:1,你可能会尝试让你的查询包含类似(':1')的东西,这样如果:1为空,它会解析为(''),这不会导致解析错误(但是如果该字段可以有空值,它可能会导致不良行为 - 尽管如果它是一个int,这不是问题)。然而,这不是一个非常干净的解决方案,你最好检测数组是否为空并且只使用缺少“IN(:1)”组件的备用版本的查询。 (如果这是WHERE子句中唯一的逻辑,那么大概你不想选择所有内容,所以你根本就不会执行查询。)

答案 4 :(得分:0)

我会使用零,假设你的“id”列是一个自动分配数字的伪代码。

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

由于零可能永远不会出现在“id”列中,因此当输入数组为空时,可以在IN()谓词中使用此值,并且它永远不会匹配。

答案 5 :(得分:-1)

我能想到的唯一方法就是让你的sqlf()函数扫描,看看特定的替换是否在“IN(”之后很快就会出现,然后如果传递的变量是一个空数组,那么在某些你肯定知道的东西中,不会出现在那一列中:"m,znmzcb~~1",例如。这是一个黑客,当然可以。但/ / p>

如果你想更进一步,你可以改变你的功能,以便有不同类型的替换?看起来您的函数扫描冒号后跟一个数字。为什么不添加另一个类型,比如@后跟一个数字,这对于清空数组是明智的(这样可以避免扫描并猜测变量是否应该是一个数组)。