代码之家  ›  专栏  ›  技术社区  ›  Adam Paynter

Oracle表单中PL/SQL布尔变量的计算

  •  12
  • Adam Paynter  · 技术社区  · 16 年前

    假设我有一个 BOOLEAN Oracle窗体中PL/SQL块中的变量:

    DECLARE
      is_viewable BOOLEAN;
    BEGIN
      is_viewable := ...;
    
      IF NOT is_viewable THEN
        raise_my_error(); // pseudo-code
      END IF;
    END;
    

    在使用调试器多次遍历此代码之后,我确定 raise_my_error() 从未 接到电话。澄清:

    • 引发我的错误() 打电话给如果 is_viewable = TRUE
    • 引发我的错误() 打电话给如果 is_viewable = FALSE

    初步测试表明,这种行为仅限于在Oracle表单中运行的PL/SQL代码,而不是直接在数据库中运行的PL/SQL代码(尽管我可能错了)。

    我可以通过显式比较来解决这个问题 is_viewable FALSE :

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

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

    更新: 我的调试器似乎没有显示正确的值,并且此问题不再有效。很抱歉你这么糊涂。

    6 回复  |  直到 16 年前
        1
  •  16
  •   Doug Porter    16 年前

    我们可以在SQLPlus中测试这一点,看看在这三种情况下(true、false、null)都会发生什么:

    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>
    

    因此,唯一可能产生预期输出的代码路径是进入条件的值是否为false。如果这不是你所看到或期待的,那么在你的过程中一定会发生其他事情或作为副作用。

        2
  •  4
  •   dcp    16 年前

    变量设置为什么值?请务必理解,如果值为空,则永远不会执行块。我不确定这是否是你的问题,但这里有一个例子:

    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会有什么不同,但也许它正在以某种方式将变量设置为null?

        3
  •  4
  •   Jeffrey Kemp    16 年前

    NOT is_viewable 评估为 TRUE 如果且仅当 is_viewable FALSE .

    对你来说, 是否可见 可能是被设定为 NULL ;在这种情况下,表单调试器可能会显示“FALSE”,从而引起混乱。

    请改为使用以下代码:

    IF NOT is_viewable THEN 
       raise_my_error();
    ELSIF is_viewable IS NULL THEN
       raise_another_error();
    END IF;
    
        4
  •  2
  •   Doug Porter    14 年前

    声明时,必须为“可见”设置初始值。声明布尔值时,Oracle不会为布尔值设置默认值。在声明布尔值时设置它的值在块内设置值可能并不总是最佳方法。如果您正在创建一个函数,而块失败了,那么您可能会得到一个没有值的返回函数,但是如果在块外部声明,并且您有一个异常处理程序,那么它将捕获并处理错误。以这种方式设置块始终是一种良好的做法。

    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 
    
        5
  •  1
  •   kurosch    16 年前

    试试看它是否改变了什么:

    IF is_viewable THEN
        NULL;
    ELSE
        raise_my_error();
    END IF;
    
        6
  •  1
  •   Alexander Malakhov Rahul R Dhobi    14 年前

    表单的版本是什么?
    我刚刚在Forms Builder 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。