【问题标题】:Evaluation of PL/SQL boolean variables in Oracle Forms在 Oracle Forms 中评估 PL/SQL 布尔变量
【发布时间】:2010-12-25 00:03:40
【问题描述】:

假设我在 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() 从不 被调用。澄清一下:

  • 如果is_viewable = TRUE,raise_my_error()not 是否会被调用
  • 如果is_viewable = FALSE raise_my_error() not 会被调用

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

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

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

我仍然很好奇为什么 NOT is_viewable 永远不会评估为 TRUE。

更新:看来我的调试器没有显示正确的值,而且这个问题不再有效。很抱歉造成这种混乱。

【问题讨论】:

  • [友情提示] 作为有经验的用户,我猜你只是忘了接受一个答案(dcp's 或 Jeffrey's)。
  • @AlexanderMalakhov:我曾多次想接受答案,但现在代码似乎运行正确,这个问题似乎无法回答。除非我弄错了,否则两个答案都无法解释为什么NOT is_viewable 会总是评估为FALSE(无论is_viewable 的值如何)而is_viewable = FALSE 会评估为TRUE 或@ 987654339@,取决于is_viewable 的值。由于问题停止发生,我无法验证任何答案。 :(
  • 明白。我有类似的(w.r.t.“没有正确答案,无法验证”)question。由于其他人回答我的问题的可能性很小,因此我决定接受最有帮助的(而不是正确的)答案。所以要奖励这个人的时间和努力。对于我的 Q 没有悬在未答复的列表中。虽然要明确一点,但我对不遵循我的策略的人完全没有问题(更重要的是,因为你显然为 SO 社区做得很好)

标签: oracle plsql boolean oracleforms


【解决方案1】:

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

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

【讨论】:

  • 很好解释.. 谢谢
【解决方案2】:

变量被设置为什么值?请理解,如果值为 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?

【讨论】:

  • 感谢您的提示!我已经理解了NULL 值的问题。但是,我目睹了这种行为(通过调试器),is_viewable 设置为TRUE 以及is_viewable 设置为FALSE。老实说,我还没有尝试过将其设置为 NULL 会发生什么......我怀疑这会对这种情况有多大帮助。
【解决方案3】:

当且仅当is_viewable 为FALSE 时,NOT is_viewable 的计算结果为TRUE。

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

试试这个代码:

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

【讨论】:

    【解决方案4】:

    您必须在声明 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 
    

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • 值得一提的是,这段代码可能隐藏了bug。例如。 myBool := (sum1 = sum2),其中sum1=0 和sum2 is null。人们可能希望这是 True 而不是 Null。
      【解决方案6】:

      Forms 的版本是多少?
      我刚刚在 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。

      【讨论】:

      • 是的,表单的版本会很有用。也是 Oracle 客户端的版本。和数据库。旧版本的 Forms 有自己的 PL/SQL 解释器,这可能会影响您。
      猜你喜欢
      • 1970-01-01
      • 2020-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-18
      • 2015-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多