Почему условие на отсутствие элемента в коллекции с 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 шт):
В этом случае, 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