MySQL中的空IN子句参数列表

时间:2012-11-03 14:51:05

标签: mysql sql in-clause

当您执行IN子句为空的SQL查询时会发生什么?

例如:

SELECT user WHERE id IN ();

MySQL是否会按预期处理此问题(即始终为false),如果没有,我的应用程序在动态构建IN子句时如何处理这种情况?

9 个答案:

答案 0 :(得分:44)

如果我有一个应用程序,我正在动态构建IN列表,并且它可能最终为空,我有时会做的是用不可能的值初始化列表并添加到该列表。例如。如果它是一个用户名列表,我将从一个空字符串开始,因为那不是一个可能的用户名。如果它是auto_increment ID,我将使用-1,因为实际值总是正数。

如果由于没有不可能的值而不可行,则必须使用条件来决定是否在AND column IN ($values)子句中包含WHERE表达式。

答案 1 :(得分:12)

您的查询与有效语法的最接近的近似值是:

SELECT user FROM tbl1 WHERE id IN (SELECT id FROM tbl1 WHERE FALSE);

将无条件地返回空结果集。括号中的子查询总是返回一个空集,正如我前面提到的,在空集中找不到任何值,因为空集不包含任何值。

答案 2 :(得分:8)

这也给了我0个结果:

SELECT id FROM User
WHERE id IN (NULL);

尝试使用MYSQL 5.6

答案 3 :(得分:3)

使用始终错误的陈述

在创建SQL之前,请检查数组大小。 如果大小为0,则将where语句生成为1 = 2,如:

SELECT * FROM USERS WHERE name in () 

变为

SELECT * FROM USERS WHERE 1 = 2 

对于空数组中的“not in”,生成一个始终为true的语句,如:

SELECT * FROM USERS WHERE name not in () 

变为

SELECT * FROM USERS WHERE 1 = 1

这应该适用于更复杂的查询:

SELECT * FROM USERS WHERE (name in () OR name = 'Alice') 

变为

SELECT * FROM USERS WHERE (1 = 2 OR name = 'Alice') 

答案 4 :(得分:3)

如果对id(1,2,3,..)使用AUTO_INCREMENT,如果数组为空,则可以添加一个项[0]。所以它将是

if (empty($arr)) {
   $arr[] = 0;
}

SELECT user WHERE id IN (0);

并且没有mysql解析错误。这种情况在子查询中非常有用 - 当您的主查询不依赖于子查询结果时。

更好的方法 - 如果数组为空,则不要调用查询。

$data = null;
if (!empty($arr)) {
    $data = ... call query
}

答案 5 :(得分:1)

我假设您IN为空时仍需要运行查询;例如LEFT JOIN ... ON ... AND IN ()

由于您已经在应用程序层中动态构建IN,我会在那里处理空案例。

这是PHP中的基本示例

$condition = 'FALSE' // Could feasibly want TRUE under different circumstances
if($values){
   $inParams = **dynamically generated IN parameters from $values**;
   $condition = 'IN (' . $inParams . ')';
}

$sql = 'SELECT * FROM `user` WHERE '.$condition;

如果您不需要使用空IN运行查询,那么请不要这样做。为自己保存一次数据库之旅!

NB 如果您还没有,我会构建/使用一个长期合作的功能,并在您的IN参数中正确绑定,而不是而不只是将它们原始连接到SQL中。如果它在原始数据上使用,这将为您提供一些防止SQL注入的保护。

答案 6 :(得分:1)

您不能将IN运算符留空,您必须在其中输入一些内容,例如NULL。但是,即使在这种情况下,它也不会按预期方式工作,因为与NULL比较总是返回NULL(空)。一种可能的解决方案是添加子选择。

示例:

SELECT user_id FROM users;

+-----------+
| user_id   |
+-----------+
|      1000 |
|      1001 |
|      1002 |
|      1003 |
|      1004 |
|      1005 |
|      1006 |
|      1007 |
|      1008 |
|      1009 |
|      1010 |
+-----------+

SELECT user_id FROM users WHERE user_id NOT IN ();
ERROR: 1064: You have an error in your SQL syntax; check the manual that 
corresponds to your MySQL server version for the right syntax to use near ')' at line 1

SELECT user_id FROM users WHERE user_id NOT IN (NULL);
Empty set (0.0003 sec)    

SELECT user_id FROM users WHERE user_id IN (1001, 1002, 1003) 
AND user_id NOT IN (SELECT user_id FROM users WHERE user_id IN (NULL));
+---------+
| user_id |
+---------+
|    1001 |
|    1002 |
|    1003 |
+---------+
3 rows in set (0.0004 sec)

您可以稍微修改(缩短)查询,但是我认为它们也会稍微慢一点。

答案 7 :(得分:0)

这是空列表的始终为假的语句的另一种形式,它保留了查询中的逻辑和实际列的概念。

错误的id in ()可以重写为:

where id <> id;

类似不正确的否定条件id not in ()可以通过自定义查询构建代码转换为:

where id = id;

这种方法比id not in (NULL)更安全,因为它不会求值为NULL。

但是请注意,这会从结果中过滤出id is null行。在某些情况下,这可能被视为功能。

对于复杂的堆叠查询构建逻辑特别有用,其中嵌套构建器不知道如何在上面使用结果子查询。

答案 8 :(得分:-1)

如果在应用程序中使用该查询,并且将对象列表动态传递给查询,那么我不应该调用数据库以使用不可能的值进行选择,我应该返回一个空列表而不调用直接进行数据库查询。

因为在调用它之前先执行一个知道为空的查询是没有意义的。