问题描述
嗨,汤姆,
我一直都知道,如果一个或两个都为NULL,则a = b和a!= b都评估为FALSE。然而,我看到一些奇怪的行为,我试图提炼和理解。
玩弄v_Var1和v_Var2,当它们都是空的,或者都是非空的和相等的,第一个测试打印 “相同” (这是完全有意义的,是一个教科书的例子)。
当它们不同时 (特别是当一个是空的,一个不是),我会期望第二个测试会打印 “不同”,但它没有。该逻辑旨在不是 <我用来测试它们是否相同的情况>。
所以我想自己,“也许v_Var1 = v_Var2并没有真正解析为FALSE,当一个是NULL-也许它解析为NULL,并且NULL与任何操作 (例如,或不) 产生NULL”-所以我尝试了第三个,这令人惊讶地工作。但如果它是真的,它的评估为NULL,我希望当两个变量都是NULL,第一个测试将评估为 (NULL或 (true和TRUE)),我本来希望导致NULL,因此被视为FALSE。所以更有可能的是,我只是因为一个我不明白的原因而幸运地发现了一些有效的东西。
所有这些都说-
1) 为什么第一个 “不同” 测试不起作用?
2) 我应该用什么代替?
3) 第三次测试实际上发生了什么?
谢谢!
我一直都知道,如果一个或两个都为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) 第三次测试实际上发生了什么?
谢谢!
专家解答
通过将其分解并打印一些结果来轻松解释:
所以让我们分解测试 #1
“边” 为null和false。而 “null或false” 为null。
这就是为什么NVL起作用而其他不起作用的原因。
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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




