“成员”集合的 PL/SQL 否定不否定

Posted

技术标签:

【中文标题】“成员”集合的 PL/SQL 否定不否定【英文标题】:PL/SQL negation of "member of" collection does not negate 【发布时间】:2015-07-16 17:24:25 【问题描述】:

我有一个 PL/SQL 集合,其中包含一个空元素(在最小的工作示例中仅此而已,但附加元素的行为是相同的)。当我现在查询此集合是否具有特定数字作为元素时,它按预期返回false。但奇怪的是,否定查询也会产生false 的答案。

任何人都可以确认这种行为或指导我在这里失败的假设吗?

DECLARE
  TYPE number_t IS TABLE OF NUMBER;
  nt1 number_t := number_t();
BEGIN
  nt1.extend();
  dbms_output.put_line('Start');        -- prints 'Start'
  IF 1 member of nt1 THEN
    dbms_output.put_line('Member');     -- does not execute
  END IF;
  IF not 1 member of nt1 THEN
    dbms_output.put_line('Not member'); -- does not execute
  END IF;
  IF not (1 member of nt1) THEN
    dbms_output.put_line('Not member'); -- does not execute
  END IF;
END;

观察时间:Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit

尚未在其他安装上进行测试。

【问题讨论】:

【参考方案1】:

根据 Oracle 文档,“EXTEND 将一个空元素附加到集合”和“如果 expr 等于指定的成员,则 [MEMBER 运算符] 的返回值是 TRUE嵌套表”

将任何内容与 null 进行比较都会得到 UNKNOWN 结果,因此条件既不是 TRUE 也不是 FALSE,因此永远不会执行 THEN 块。

参考资料:

    http://docs.oracle.com/cd/B12037_01/appdev.101/b10807/13_elems006.htm

    http://docs.oracle.com/cd/B19306_01/server.102/b14200/conditions006.htm

【讨论】:

有什么方法可以检查UNKNOWN 结果的样子吗?例如,通过将 MEMBER 的结果分配给变量,而不像 CASE 那样实际分配/转换为布尔值? 不确定UNKNOWN 的“外观”是什么意思。它属于BOOLEAN 之类,但既不是TRUE 也不是FALSE,因此如果将其分配给布尔变量,其值也将变为UNKNOWN 谢谢,我不知道 BOOLEANUNKNOWN 值实际上是 IS NULL。因此,检查not MEMBER 的正确方法是同时检查NULL【参考方案2】:

为了完整起见,考虑到可能的NULL 值,我检查not MEMBER 的最终方法是:

IF not 1 member of nt1 OR (1 member of nt1) IS NULL THEN
  dbms_output.put_line('NULL'); -- prints 'NULL'
END IF;

【讨论】:

以上是关于“成员”集合的 PL/SQL 否定不否定的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL ORA-01422 SELECT INTO 错误,Oracle 匿名块(NOVA 环境)

将PL/SQL代码封装在机灵的包中

Windows 64位 安装Oracle instantclient 官方绿色版和PL/SQL Developer 总结

在使用 Entity Framework 数据库优先在表上插入行之前,如何从 PL/SQL 执行触发器?

如何在选择语句的“NOT IN”子句中使用逗号分隔的字符串列表作为 pl/sql 存储的函数参数

PL/SQL developer连接oracle出现“ORA-12154:TNS:could not resolve the connect identifier specified”问题的解决(代码