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() 永远不会被调用。澄清:

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

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

我可以通过明确比较is_viewable来解决这个问题FALSE

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

我仍然很好奇为什么NOT is_viewable从不评估到TRUE

更新:看来我的调试器没有显示正确的值,这个问题不再有效。对这种混乱感到抱歉。

4

6 回答 6

19

我们可以在 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>

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

于 2009-12-31T07:08:27.703 回答
4

NOT is_viewable计算TRUE当且仅当is_viewableis FALSE

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

试试这个代码:

IF NOT is_viewable THEN 
   raise_my_error();
ELSIF is_viewable IS NULL THEN
   raise_another_error();
END IF;
于 2009-12-10T03:15:20.363 回答
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 会有什么不同,但也许它以某种方式将变量设置为 null?

于 2009-12-09T20:38:29.570 回答
2

声明时必须为 is_viewable 设置一个初始值。Oracle 在声明 BOOLEAN 时不会为其设置默认值。在声明时设置 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 
于 2011-06-01T03:49:01.097 回答
1

表格的版本是多少?
我刚刚在 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 添加到示例。

于 2010-02-10T07:05:34.733 回答
1

试试这个,看看它是否改变了什么:

IF is_viewable THEN
    NULL;
ELSE
    raise_my_error();
END IF;
于 2009-12-16T18:46:14.083 回答