Предикат Db2 IN выдает NULL при сравнении константы с пустым набором - PullRequest
2 голосов
/ 14 апреля 2020

Рассмотрим этот запрос:

SELECT 
  1 IN (
    SELECT 1 FROM SYSIBM.dual WHERE FALSE  
  ) AS a,
  1 IN (
    SELECT NULL FROM SYSIBM.dual WHERE FALSE
  ) AS b
FROM SYSIBM.dual;

Оба предиката проверяют, находится ли постоянное значение в пустом наборе. Единственное отличие состоит в том, что в одном из пустых наборов содержится NULL литерал, что, на мой взгляд, не имеет значения. Оба результата должны быть FALSE, потому что в пустом наборе никогда не бывает значений. Тем не менее, я получаю это:

A|B|
-|-|
0| |

A это FALSE, как и ожидалось, но B IS NULL, что не имеет смысла. Использование CAST(NULL AS INT) ничего не меняет, так как это могло произойти из-за неизвестных типов данных. Есть ли логическое объяснение этому поведению или это ошибка? И MySQL, и PostgreSQL возвращают FALSE для B.

-- PostgreSQL:
SELECT 
  1 IN (
    SELECT 1 WHERE FALSE  
  ) AS a,
  1 IN (
    SELECT CAST(NULL AS INT) WHERE FALSE
  ) AS b

-- MySQL:
SELECT 
  1 IN (
    SELECT 1 WHERE FALSE  
  ) AS a,
  1 IN (
    SELECT NULL WHERE FALSE
  ) AS b

Более простой пример демонстрирует похожую ошибку (возможно, связанную с ошибочной реализацией типа BOOLEAN Db2 в general ):

SELECT NULL OR FALSE AS a, FALSE OR NULL AS b FROM SYSIBM.dual; 

Который производит:

A|B|
-|-|
0| |

Очевидно, еще одна ошибка. Порядок операндов в OR не должен иметь значения.

Я использую Db2 LUW v11.5.0.0

1 Ответ

0 голосов
/ 14 апреля 2020

IN дает значение NULL по сравнению со значениями NULL из-за недоступности IS NULL с использованием IN

. Вы получили правильный вывод (поскольку это условия или подобные тестовые случаи), результаты не логические, а в форме 0 или данных (true), поскольку первый запрос оценивается как ложный, что означает эквивалент 0, поскольку IN не дает значений, будет 0, как если бы (проверка данных).

Однако, для второго он возвращает ноль как IN в случае NULL сравнение завершается неудачно из-за отсутствия IS NULL, следовательно, true он считает нулевым. Я думаю, что поведение несколько похоже на троичный условный оператор

      Select IN? 0(true) |DATA (includes 
      NULL) (false) 
...