Почему условие на отсутствие элемента в коллекции с NOT MEMBER OF всегда FALSE?

Есть коллекция, которая содержит пустой элемент. Когда проверяю условие, содержит ли эта коллекция несуществующий в ней элемент, она возвращает false, как и ожидалось.

Но странно то, что отрицание этого же условия также даст ответ false:

DECLARE
    TYPE number_t IS TABLE OF NUMBER;
    nt1 number_t := number_t();
BEGIN
    nt1.extend(2);
    nt1(1) := 2;
    dbms_output.put_line('Start');
    IF 2 member of nt1 THEN
        dbms_output.put_line('2 member');
    END IF;
    IF 1 member of nt1 THEN
        dbms_output.put_line('1 member');
    END IF;
    IF 1 NOT member of nt1 THEN
        dbms_output.put_line('1 NOT member');
    END IF;
END;
/
Start
2 member

В чём причина такого поведения, или что-то делаю не так?


Свободный перевод вопроса PL/SQL negation of "member of" collection does not negate от участника @Michael Lang


Ответы (1 шт):

Автор решения: 0xdb

В этом случае, MEMBER OF вернёт NULL.

Результат сравнения зачения с NULL не является ни TRUE, ни FALSE, а именно NULL.
Следовательно, ни одно из условий ниже, никогда не выполнится:

IF 1 = NULL THEN [...]
IF NOT 1 = NULL THEN [...] 

Почему MEMBER OF, при наличии в коллекции одного единственного NULL элемента и отсутствии проверяемого элемента, вернёт NULL, а не FALSE? Потому что, оба метода определения, является ли элемент членом коллекции, в примере ниже - эквивалентны:

declare
    type numbertab is table of number;
    nt numbertab := numbertab (2, null);
begin
    dbms_output.put_line ('array is '||case when nt is empty then 'empty' else 'not empty' 
        end||' and has '||nt.count||' element(s)');

    dbms_output.put_line ('with member of result is '||
        case when (1 member of nt) is null then 'null' else 'not null' end);

    dbms_output.put_line ('with condition result is '||
        case when (1 = nt(1) or 1 = nt(2)) is null then 'null' else 'not null' end);
end;
/
array is not empty and has 2 element(s)
with member of result is null
with condition result is null

В документации о поведении MEMBER OF в случае наличия NULL элемента, ничего не упомянуто:

MEMBER Condition
The return value is TRUE if expr is equal to a member of the specified nested table or varray.
The return value is NULL if expr is null or if the nested table is empty.


Кого такое поведение не устраивает, может воспользоваться функциями по работе с NULL:

declare
    type numbertab is table of number;
    nt numbertab := numbertab (2, null);
begin
    dbms_output.put_line ('1 is '||
        case when NOT coalesce (1 member of nt, false) then 'not member' end);
    dbms_output.put_line ('2 is '||
        case when     coalesce (2 member of nt, false) then 'member' end);
end;
/
1 is not member
2 is member
→ Ссылка