IN子句为NULL或IS NULL

Phi*_*ord 69 sql postgresql null in-clause conditional-statements

Postgres是数据库

我可以为IN子句使用NULL值吗?例:

SELECT *
FROM tbl_name
WHERE id_field IN ('value1', 'value2', 'value3', NULL)
Run Code Online (Sandbox Code Playgroud)

我想限制这四个值.

我已经尝试了上面的语句,它不起作用,它执行但不添加NULL id_fields的记录.

我还试图添加一个OR条件,但这只是使查询运行并运行,看不到任何结束.

SELECT *
FROM tbl_name
WHERE other_condition = bar
AND another_condition = foo
AND id_field IN ('value1', 'value2', 'value3')
OR id_field IS NULL
Run Code Online (Sandbox Code Playgroud)

有什么建议?

Dan*_*ite 94

一个in声明将相同解析到field=val1 or field=val2 or field=val3.在那里放一个null将归结为field=null哪个不起作用.

(注释马克乙)

我会这样做是为了苛刻

SELECT *
FROM tbl_name
WHERE 
(id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)
Run Code Online (Sandbox Code Playgroud)

  • @Phill - 这是一个操作顺序问题。 (2认同)

Erw*_*ter 19

由于运算符优先级,您的查询失败.AND以前绑定OR!
你需要一对括号,这不是"清晰度"的问题,而是纯粹的逻辑必然性.

SELECT *
FROM   tbl_name
WHERE  other_condition = bar
AND    another_condition = foo
AND   (id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)
Run Code Online (Sandbox Code Playgroud)

添加的括号AND之前会阻止绑定OR.如果没有其他WHERE条件(不AND),则不需要括号.接受的答案在这方面有点误导.


Ove*_*eth 8

SELECT *
FROM tbl_name
WHERE coalesce(id_field,'unik_null_value') 
IN ('value1', 'value2', 'value3', 'unik_null_value')
Run Code Online (Sandbox Code Playgroud)

这样你就可以从检查中消除空值.给定id_field中的空值,coalesce函数将返回null而不返回'unik_null_value',并且通过将'unik_null_value'添加到IN列表,查询将返回id_field为value1-3或null的帖子.

  • 一点点解释对未来的读者有所帮助.您的代码如何帮助解决问题? (2认同)

Sus*_*tta 7

丹尼尔回答的问题非常好.我想留下关于NULLS的说明.当列包含NULL值时,我们应该小心使用NOT IN运算符.如果列包含NULL值并且您正在使用NOT IN运算符,则不会获得任何输出.这就是它在http://www.oraclebin.com/2013/01/beware-of-nulls.html上的解释,这是一篇非常好的文章,我遇到过并想过分享它.


100*_*111 6

注意:由于有人声称外部链接在Sushant Butta 的回答中已失效,因此我已将内容作为单独的回答发布在此处。

当心NULLS

今天我在使用 IN 和NOT IN运算符时遇到了一个非常奇怪的查询行为。实际上,我想比较两个表并找出其中是否table b存在一个值,table a并在该列包含null值时找出其行为。所以我刚刚创建了一个环境来测试这种行为。

我们将创建表table_a

SQL> create table table_a ( a number);
Table created.
Run Code Online (Sandbox Code Playgroud)

我们将创建表table_b

SQL> create table table_b ( b number);
Table created.
Run Code Online (Sandbox Code Playgroud)

将一些值插入到table_a.

SQL> insert into table_a values (1);
1 row created.

SQL> insert into table_a values (2);
1 row created.

SQL> insert into table_a values (3);
1 row created.
Run Code Online (Sandbox Code Playgroud)

将一些值插入到table_b.

SQL> insert into table_b values(4);
1 row created.

SQL> insert into table_b values(3);
1 row created.
Run Code Online (Sandbox Code Playgroud)

现在我们将执行一个查询,table_a通过table_b使用IN运算符检查其值来检查值是否存在。

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3
Run Code Online (Sandbox Code Playgroud)

执行以下查询以检查不存在。

SQL> select * from table_a where a not in (select * from table_b);
         A
----------
         1
         2
Run Code Online (Sandbox Code Playgroud)

输出符合预期。现在我们将null在表中插入一个值table_b并查看上述两个查询的行为。

SQL> insert into table_b values(null);
1 row created.

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

SQL> select * from table_a where a not in (select * from table_b);

no rows selected
Run Code Online (Sandbox Code Playgroud)

第一个查询按预期运行,但是第二个查询发生了什么?为什么我们没有得到任何输出,应该发生什么?查询有什么不同吗?没有

变化是在 table 的数据中table_b。我们null在表中引入了一个值。但它怎么会这样呢?让我们将两个查询拆分为"AND"and"OR"运算符。

第一个查询:

第一个查询将在内部像这样处理。所以 anull不会在这里产生问题,因为我的前两个操作数将评估为truefalse。但是我的第三个操作数a = null既不会评估true也不会false。它只会评估为null

select * from table_a whara a = 3 or a = 4 or a = null;

a = 3  is either true or false
a = 4  is either true or false
a = null is null
Run Code Online (Sandbox Code Playgroud)

第二个查询:

第二个查询将按如下方式处理。由于我们使用的是"AND"运算符,因此除true任何操作数之外的任何内容都不会给我任何输出。

select * from table_a whara a <> 3 and a <> 4 and a <> null;

a <> 3 is either true or false
a <> 4 is either true or false
a <> null is null
Run Code Online (Sandbox Code Playgroud)

那么我们该如何处理呢?我们将在使用运算符时not null从表中选择所有值。table_bNOT IN

SQL> select * from table_a where a not in (select * from table_b where b is not null);

         A
----------
         1
         2
Run Code Online (Sandbox Code Playgroud)

因此NULL,在使用NOT IN运算符时,请始终注意列中的值。

小心空值!!