暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 带有非布尔值和布尔值的空值

askTom 2018-03-02
354

问题描述

嗨,汤姆,
我一直都知道,如果一个或两个都为NULL,则a = b和a!= b都评估为FALSE。然而,我看到一些奇怪的行为,我试图提炼和理解。

DECLARE
    v_Var1 VARCHAR2(12) := 'A';
    v_Var2 VARCHAR2(12) := NULL;
BEGIN
    --WORKS WHEN BOTH ARE NULL OR BOTH ARE NON-NULL AND EQUAL
    IF (v_Var1 = v_Var2 OR (v_Var1 IS NULL AND v_Var2 IS NULL)) THEN
        DBMS_OUTPUT.PUT_LINE('Same');
    END IF;
    --SAME TEST AS ABOVE, wrapped in NOT
    IF NOT((v_Var1 = v_Var2 OR (v_Var1 IS NULL AND v_Var2 IS NULL))) THEN
        DBMS_OUTPUT.PUT_LINE('Different');
    END IF;
    --WORKS, BUT I DON'T KNOW WHY
    IF NOT((NVL(v_Var1 = v_Var2,false) OR (v_Var1 IS NULL AND v_Var2 IS NULL))) THEN
        DBMS_OUTPUT.PUT_LINE('Different (if NULL=NULL is NULL)');
    END IF;
END;


玩弄v_Var1和v_Var2,当它们都是空的,或者都是非空的和相等的,第一个测试打印 “相同” (这是完全有意义的,是一个教科书的例子)。

当它们不同时 (特别是当一个是空的,一个不是),我会期望第二个测试会打印 “不同”,但它没有。该逻辑旨在不是 <我用来测试它们是否相同的情况>。

所以我想自己,“也许v_Var1 = v_Var2并没有真正解析为FALSE,当一个是NULL-也许它解析为NULL,并且NULL与任何操作 (例如,或不) 产生NULL”-所以我尝试了第三个,这令人惊讶地工作。但如果它是真的,它的评估为NULL,我希望当两个变量都是NULL,第一个测试将评估为 (NULL或 (true和TRUE)),我本来希望导致NULL,因此被视为FALSE。所以更有可能的是,我只是因为一个我不明白的原因而幸运地发现了一些有效的东西。

所有这些都说-
1) 为什么第一个 “不同” 测试不起作用?
2) 我应该用什么代替?
3) 第三次测试实际上发生了什么?

谢谢!

专家解答

通过将其分解并打印一些结果来轻松解释:

SQL> set serverout on
SQL> DECLARE
  2      v_Var1 VARCHAR2(12) := 'A';
  3      v_Var2 VARCHAR2(12) := NULL;
  4
  5      b boolean;
  6
  7      procedure print_bool(p boolean) is
  8      begin
  9        if p is null then
 10           dbms_output.put_line('null');
 11        elsif p then
 12           dbms_output.put_line('true');
 13        else
 14           dbms_output.put_line('false');
 15        end if;
 16     end;
 17  BEGIN
 18      b := (v_Var1 = v_Var2 OR (v_Var1 IS NULL AND v_Var2 IS NULL)) ;
 19      print_bool(b);
 20
 21      b := NOT((v_Var1 = v_Var2 OR (v_Var1 IS NULL AND v_Var2 IS NULL))) ;
 22      print_bool(b);
 23
 24      b := NOT((NVL(v_Var1 = v_Var2,false) OR (v_Var1 IS NULL AND v_Var2 IS NULL))) ;
 25      print_bool(b);
 26  END;
 27  /
null
null
true

PL/SQL procedure successfully completed.


所以让我们分解测试 #1

SQL> set serverout on
SQL> DECLARE
  2      v_Var1 VARCHAR2(12) := 'A';
  3      v_Var2 VARCHAR2(12) := NULL;
  4
  5      b boolean;
  6
  7      procedure print_bool(p boolean) is
  8      begin
  9        if p is null then
 10           dbms_output.put_line('null');
 11        elsif p then
 12           dbms_output.put_line('true');
 13        else
 14           dbms_output.put_line('false');
 15        end if;
 16     end;
 17  BEGIN
 18
 19  --
 20  -- Components of test #1
 21  --
 22      b := v_Var1 = v_Var2;
 23      print_bool(b);
 24      b := (v_Var1 IS NULL AND v_Var2 IS NULL);
 25      print_bool(b);
 26
 27  END;
 28  /
null
false

PL/SQL procedure successfully completed.


“边” 为null和false。而 “null或false” 为null。

这就是为什么NVL起作用而其他不起作用的原因。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论