2009-12-09 82 views
11

假设我有一个Oracle表一个PL/SQL块内的BOOLEAN变量:评估表

DECLARE 
    is_viewable BOOLEAN; 
BEGIN 
    is_viewable := ...; 

    IF NOT is_viewable THEN 
    raise_my_error(); // pseudo-code 
    END IF; 
END; 

通过这个代码几次调试器步进之后,我有确定raise_my_error()从来没有被调用。为了澄清:

  • raise_my_error()得到,如果is_viewable = TRUE
  • raise_my_error()被调用,如果is_viewable = FALSE

初步试验表明,这种行为被限制在PL/SQL代码的运行叫在Oracle Forms中,而不是在数据库中直接运行PL/SQL代码(尽管我可能是错的)。

我可以明确地比较is_viewableFALSE解决这个问题:

IF is_viewable = FALSE THEN 
    raise_my_error(); 
END IF; 

我仍然好奇,为什么NOT is_viewable从不计算TRUE

更新:看来我的调试器没有显示正确的值,并且此问题不再有效。对于这种困惑感到抱歉。

+0

[友情提示]因为你是有经验的用户,我想你只是忘了接受一个答案(dcp's或Jeffrey's)。 –

+0

@AlexanderMalakhov:我有几次想接受一个答案,但是现在问题似乎是无法回答的,因为代码似乎运行正常。除非我误解了,否则答案都不能解释为什么NOT_viewable'总是**评估为FALSE(不管is_viewable的值如何),而is_viewable = FALSE将评估为TRUE或' FALSE',取决于'is_viewable'的值。由于问题停止发生,我无法验证任何答案。 :( –

+0

了解。我有类似的(“没有正确答案,无法验证”)[question](http://stackoverflow.com/questions/2233856/oracle-forms-6i-crashes-with-0xc0000005-at因为其他人永远不会回答我的Q,所以我决定接受*最有用的*(而不是正确的)回答。他的时间和努力,对于我的问题没有在悬而未决的问题列表中悬而未决,虽然很清楚,我完全没有问题,不跟随我的策略的人(更重要的是,你显然为SO社区做了很棒的工作) –

回答

4

变量被设置为什么值?要明白,如果值为null,块将永远不会执行。我不知道如果这是你的问题,但这里有一个例子:

DECLARE 
is_viewable BOOLEAN; 
BEGIN 
    IF NOT is_viewable 
    THEN 
     /* this won't execute */ 
     dbms_output.put_line('nope'); 
    END IF; 
    IF is_viewable 
    THEN 
     /* neither will this */ 
     dbms_output.put_line('nope'); 
    END IF; 
END; 

当然,我不知道怎么的Oracle Forms会做不同的,但也许它的设置变量以某种方式为空?

+0

感谢您的提示!我已经理解了NULL值的问题,但是我目睹了这种行为(通过调试器),其中'is_viewable'设置为'TRUE',以及'is_viewable'设置为'FALSE'。说实话,我没有试过看到如果它被设置为NULL,会发生什么......我怀疑它会对情况有很大帮助。 –

4

NOT is_viewable评估为TRUE当且仅当is_viewableFALSE

在你的情况下,is_viewable可能被设置为NULL;在这种情况下,Forms调试器可能会显示“FALSE”导致混淆。

试试这个代码,而不是:

IF NOT is_viewable THEN 
    raise_my_error(); 
ELSIF is_viewable IS NULL THEN 
    raise_another_error(); 
END IF; 
1

试试这个,看看它改变任何东西:

IF is_viewable THEN 
    NULL; 
ELSE 
    raise_my_error(); 
END IF; 
+1

值得一提的是,这段代码可能会隐藏错误。例如。 'myBool:=(sum1 = sum2)',其中'sum1 = 0'和'sum2为null'。人们可能会希望这是“真”而不是零。 –

13

我们可以在sqlplus测试此看到在每个3分的情况下会发生什么(真,假,空):

set serveroutput on 

declare 
    true_value boolean := true; 
    false_value boolean := false; 
    null_value boolean; 
begin 

    if not true_value then --Should not pass 
     dbms_output.put_line('True Value'); 
    end if; 

    if not false_value then --Should pass 
     dbms_output.put_line('False Value'); 
    end if; 

    if null_value is null then --Just to make sure it is null 
     dbms_output.put_line('Null Value is Null'); 
    end if; 

    if not null_value then --Should not pass 
     dbms_output.put_line('Null Value'); 
    end if; 
end; 
/

主要生产:

SQL> set serveroutput on 
SQL> 
SQL> declare 
    2 true_value boolean := true; 
    3 false_value boolean := false; 
    4 null_value boolean; 
    5 begin 
    6 
    7  if not true_value then --Should not pass 
    8  dbms_output.put_line('True Value'); 
    9  end if; 
10 
11  if not false_value then --Should pass 
12  dbms_output.put_line('False Value'); 
13  end if; 
14 
15  if null_value is null then --Just to make sure it is null 
16  dbms_output.put_line('Null Value is Null'); 
17  end if; 
18 
19  if not null_value then --Should not pass 
20  dbms_output.put_line('Null Value'); 
21  end if; 
22 end; 
23/
False Value 
Null Value is Null 

PL/SQL procedure successfully completed. 

SQL> 

所以唯一可能的代码路径可以产生您的预期输出是如果进入条件的值是假的。如果这不是你所看到或期望的,那么你的手术中必须发生其他事情,或者作为副作用。

+0

很好解释..谢谢 – artapart

1

Forms的版本是什么?
我只是试着在表单生成器6I下面的代码和它的作品如预期

DECLARE 
    bTest BOOLEAN; 
BEGIN 
    bTest := FALSE; 
    IF NOT bTest THEN 
     MESSAGE('NOT FALSE passed'); 
     PAUSE; 
    END IF; 

    bTest := TRUE; 
    IF bTest THEN 
     MESSAGE('TRUE passed'); 
     PAUSE; 
    END IF; 

    bTest := NULL; 
    IF bTest OR (NOT bTest) THEN 
     MESSAGE('You will never see this message'); 
     PAUSE; 
    END IF; 
END; 

这是否工作在您的环境?

编辑将null加入示例。

+0

是的,表单的版本会很有用。也是Oracle客户端的版本。和数据库。较早版本的Forms有自己的PL/SQL解释器,可能会影响到您。 –

2

声明时必须为is_viewable设置初始值。声明时,Oracle不为BOOLEANS设置默认值。设置BOOLEAN的值时,声明设置块内的值可能并不总是最好的想法。如果您正在创建一个函数并且该块失败,那么您可能会得到一个没有值的函数,但是如果在块外部声明并且您有一个异常处理程序,那么它将捕获并处理该错误。以这种方式设置模块总是一个很好的做法。

DECLARE 
    bTest BOOLEAN := FALSE; 

BEGIN 

--in your test check for the most likely thing that would happen 
--if bTest would in most instances evaluate to be FALSE then that should be your check 

    IF NOT bTest THEN 


    MESSAGE('True Passed'); 

    ELSE 

    MESSAGE('False Passed'); 


    END IF; 

--in the event that an exception occurs or the block fails 
--the function would still return a value 

EXCEPTION WHEN NO_DATA_FOUND THEN 
    bTest := FALSE; 

WHEN OTHERS THEN 
     bTest := FALSE; 


END