Пункт IN з NULL або IS NULL


83

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

Будь-які пропозиції?


10
Вираз inбуде проаналізовано ідентично field=val1 or field=val2 or field=val3. Введення туди нуля зведеться до того, field=nullщо не буде працювати.
Marc B

1
2-й запит повинен бути правильним. що ще є у вашому whereреченні?
Daniel A. White

@Daniel A. White, оновлений з урахуванням запиту з додатковими умовами
Phill Pafford

Відповіді:


122

Вираз inбуде проаналізовано ідентично field=val1 or field=val2 or field=val3. Введення туди нуля зведеться до того, field=nullщо не буде працювати.

( Коментар від Marc B )

Я б зробив це для ясності

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

Ааа, це вдалося, дякую! Отже, обтікання полів додає обидві умови до речення WHERE? Тільки для роз’яснень
Філл Паффорд,

1
@Phill - це була проблема порядку роботи.
Daniel A. White

20

Ваш запит не вдається через перевагу оператора . 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)

Додані дужки попереджають ANDприв’язку раніше OR. Якби не було інших WHEREумов (ні AND), вам не потрібні дужки. Прийнята відповідь дещо вводить в оману.


15
SELECT *
FROM tbl_name
WHERE coalesce(id_field,'unik_null_value') 
IN ('value1', 'value2', 'value3', 'unik_null_value')

Таким чином, ви усунете нуль із перевірки. Враховуючи нульове значення в id_field, функція злиття замість null повертає 'unik_null_value', а додаючи 'unik_null_value до IN-списку, запит повертає повідомлення, де id_field має значення1-3 або null.


2
Невелике пояснення було б корисним для майбутніх читачів. Як ваш код допомагає вирішити проблему?
showdev

9

Запитання, на яке відповів Даніель, цілком чудове. Я хотів залишити записку щодо НУЛЬ. Ми повинні бути обережними щодо використання оператора NOT IN, коли стовпець містить значення NULL. Ви не отримаєте жодного результату, якщо ваш стовпець містить значення NULL і ви використовуєте оператор NOT IN. Ось як це пояснюється тут http://www.oraclebin.com/2013/01/beware-of-nulls.html , дуже гарна стаття, до якої я натрапив і думав поділитися нею.


Не впевнений, скільки користувачів стикалися з цією проблемою, але у мене виникла саме ця проблема, пов’язана із зміною нулів та оператора NOT IN, і я перебирав це протягом останніх двох годин. ЦЕ є зловмисником ...
Govind Rai

1
Посилання мертве.
Dag Høidahl

1
Подібне зараз живе.
постійно навчається

3

Примітка: Оскільки хтось стверджував, що зовнішнє посилання мертве у відповіді Сушанта Бутти, я розмістив вміст тут як окрему відповідь.

Остерігайтеся НУЛЬ .

Сьогодні я натрапив на дуже дивну поведінку запитів під час використання 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".

Перший запит:

Перший запит буде оброблятися внутрішньо приблизно так. Отже, a тут 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оператора.

Остерігайтеся НУЛЯ !!


Відмінна відповідь. Я щойно виявив проблему у своїй роботі. Дуже дуже дивна поведінка Oracle.
опутик

0

Я знаю, що пізно відповісти, але може бути корисним для когось іншого. Ви можете використовувати підзапит і перетворити нуль на 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)

Це схоже на відповідь Ове Халсета за допомогою злиття.
user890332

0

Nullвідноситься до відсутності даних. Nullформально визначається як значення, яке недоступне, неприсвоєне, невідоме або непридатне (OCA Oracle Database 12c, Керівництво з іспиту з основ SQL, с. Отже, ви не зможете побачити записи зі стовпцями, що містять нульові значення, коли вказані стовпці обмежені за допомогою речень "in" або "not in".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.