我注意到SQL Server中有以下奇怪的行为

SELECT *
FROM Tbl
WHERE col NOT IN ((SELECT 1 WHERE 1 = 2))

返回all条记录(即,子查询结果为空集)

SELECT *
FROM Tbl
WHERE col NOT IN (1, (SELECT 1 WHERE 1 = 2))

返回no条记录(即子查询结果为空)

在使用PostgreSQL和MySQL的DBFdle中获得了相同的结果.由于额外的圆括号,Sqlite在两个查询中都不返回任何记录.

我的 idea 完全错了吗?

documentation中找不到任何东西.

背景是我有一个将@Param转换为@Param1, @Param2, @Param3...的方法,其中参数的数量来自一个序列.

我希望该方法也适用于空序列,在这种情况下,我将其替换为(SELECT null WHERE 1 = 2),但当输入为NOT IN (1, @Param)时,它不起作用

有什么其他的解决方案吗?

这是小提琴的代码

CREATE TABLE Tbl (col int NOT NULL);
INSERT INTO Tbl VALUES (1);
INSERT INTO Tbl VALUES (2);

我预计第二个查询将返回"2"

推荐答案

IN的语法是

test_expression [ NOT ] IN   
    ( subquery | expression [ ,...n ]  
    )   

在第一个示例中,您使用的是subquery路由.

在第二个示例中,您提供了一个包含expression个元素的列表.这些是标量值.只有当子查询可以被强制为标量值(返回01行)时,才能在此上下文中接受子查询

通常情况下,空结果集在用作标量值时会返回NULL.

你也可以看到这一点

SELECT 1, (SELECT 1 WHERE 1 = 2)

test_expression NOT IN(NULL) returns no rows.

这是与test_expression NOT IN (empty_set)完全相反的行为(返回每一行,包括test_expressionNULL的行)

您可以将值与UNION ALL组合,以将其保留为子查询,并防止将空集强制为NULL

SELECT *
FROM   Tbl
WHERE  col NOT IN (SELECT 1 WHERE  1 = 2
                   UNION ALL
                   SELECT 1) 

Sql相关问答推荐

SQL查询以创建手头的流动余额?

LAG函数通过丢弃空值返回前一行

从以前的非空值行中获取值

在Golang中管理数据库事务的简洁方法

有没有办法在每次计算每一行的数据时更新2个值?

为表中每个缺少的引用创建新行

如何使用WSO2将空值传递给我的SQL Server存储过程?

使用WHERE子句进行筛选时,SQL SELECT查询返回总计数

如何根据同一表中某一列中的值重新排列行(仅输出它们)(重新排序)?

如何在连接中使用三个不同的列,从而在PostgreSQL中只获得两个列?

其中使用表名作为;行值;记录?

Netezza SQL:判断两个表是否相同

根据时间值提取记录

Select 组中的第一行,但在并发环境中

在where语句中使用CTE非常缓慢

PostgreSQL中如何提取以特定字符开头的字符串中的所有单词?

基于 Snowflake 的最大值创建新列

如何获取每个组中最近的n条记录并将它们聚合成数组

如何在 Oracle 中获取此变量的值?

在sql server中创建唯一标识符列