В предложении с NULL или NULL - PullRequest
65 голосов
/ 15 июня 2011

Postgres - это база данных

Могу ли я использовать значение NULL для предложения IN? Пример:

SELECT *
FROM tbl_name
WHERE id_field IN ('value1', 'value2', 'value3', NULL)

Я хочу ограничиться этими четырьмя значениями.

Я пробовал приведенное выше утверждение, и оно не работает, хорошо, что выполняется, но не добавляет записи с NULL id_fields.

Я также попытался добавить условие ИЛИ, но это просто заставило запрос выполняться и выполняться без конца.

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

Есть предложения?

Ответы [ 6 ]

89 голосов
/ 15 июня 2011

Оператор in будет проанализирован идентично field=val1 or field=val2 or field=val3.Помещение нуля туда приведет к field=null, который не будет работать.

( Комментарий от Марк B )

Я бы сделал это для ясности

SELECT *
FROM tbl_name
WHERE 
(id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)
18 голосов
/ 11 февраля 2013

Ваш запрос не выполнен из-за приоритета оператора .AND связывается до OR!
Вам нужна пара круглых скобок, которая не является вопросом "ясности", но чистой логической необходимости .

SELECT *
FROM   tbl_name
WHERE  other_condition = bar
AND    another_condition = foo
AND   <b>(</b>id_field IN ('value1', 'value2', 'value3') <b>OR</b> id_field IS NULL<b>)</b>

добавленные скобки предотвращают привязку AND перед OR.Если бы не было других условий WHERE (нет AND), вам бы не понадобилось скобок .Принятый ответ немного вводит в заблуждение в этом отношении.

7 голосов
/ 12 сентября 2016
SELECT *
FROM tbl_name
WHERE coalesce(id_field,'unik_null_value') 
IN ('value1', 'value2', 'value3', 'unik_null_value')

Чтобы вы исключили из проверки ноль. Учитывая нулевое значение в id_field, функция coalesce вместо null вернет 'unik_null_value', и, добавив 'unik_null_value в IN-список, запрос будет возвращать сообщения, где id_field равен value1-3 или null.

7 голосов
/ 11 февраля 2013

На вопрос, на который ответил Даниил, все в порядке.Я хотел оставить записку о NULLS.Мы должны быть осторожны с использованием оператора NOT IN, когда столбец содержит значения NULL.Вы не получите никакого вывода, если ваш столбец содержит значения NULL и вы используете оператор NOT IN.Вот как это объясняется здесь http://www.oraclebin.com/2013/01/beware-of-nulls.html, очень хорошая статья, с которой я столкнулся и подумал поделиться ею.

2 голосов
/ 05 октября 2017

Примечание: Поскольку кто-то утверждал, что внешняя ссылка устарела в Ответ Sushant Butta Я разместил здесь контент в качестве отдельного ответа.

Остерегайтесь NULLS .

Сегодня я столкнулся с очень странным поведением запросов при использовании операторов IN и NOT IN.На самом деле я хотел сравнить две таблицы и выяснить, существует ли значение из table b в table a или нет, и выяснить его поведение, если столбец содержит значения null.Поэтому я просто создал среду для проверки этого поведения.

Мы создадим таблицу table_a.

SQL> create table table_a ( a number);
Table created.

Мы создадим таблицу table_b.

SQL> create table table_b ( b number);
Table created.

Вставьте некоторые значения в 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.

Вставьте некоторые значения в table_b.

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

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

Теперь мы выполним запрос для проверки существования значения в table_a, проверяя его значение из table_b с помощью оператора IN.

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);
         A
----------
         1
         2

Вывод получен, как ожидалось.Теперь мы вставим 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

Первый запрос вел себя как ожидалось, но что случилось со вторым запросом?Почему мы не получили никакого выхода, что должно было случиться?Есть ли разница в запросе? Нет .

Изменение в данных таблицы table_b.Мы ввели значение null в таблице.Но почему это так?Давайте разделим два запроса на операторы "AND" и "OR".

Первый запрос:

Первый запрос будет внутренне обработан примерно так.Так что null не создаст здесь проблему, так как мои первые два операнда будут иметь значение true или false.Но мой третий операнд 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

Второй запрос:

Второй запрос будет обработан, как показано ниже.Поскольку мы используем оператор "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

Так как мы справимся с этим?Мы выберем все значения not null из таблицы table_b при использовании оператора NOT IN.

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

         A
----------
         1
         2

Поэтому всегда будьте осторожны со значениями NULL в столбце при использовании оператора NOT IN.

Остерегайтесь NULL !!

0 голосов
/ 24 января 2018

Я знаю, что уже поздно отвечать, но может быть полезно для кого-то еще. Вы можете использовать подзапрос и преобразовать ноль в 0

SELECT *
FROM (SELECT CASE WHEN id_field IS NULL 
                THEN 0 
                ELSE id_field 
            END AS id_field
      FROM tbl_name) AS tbl
WHERE tbl.id_field IN ('value1', 'value2', 'value3', 0)
...