【问题标题】:PL/SQL Evaluation OrderPL/SQL 评估顺序
【发布时间】:2008-10-09 16:36:11
【问题描述】:

你好。考虑以下几点:

SQL> DECLARE
  2     b1   BOOLEAN;
  3     b2   BOOLEAN;
  4     FUNCTION checkit RETURN BOOLEAN IS
  5     BEGIN
  6        dbms_output.put_line('inside checkit');
  7        RETURN TRUE;
  8     END checkit;
  9  
 10     PROCEDURE outp(n VARCHAR2, p BOOLEAN) IS
 11     BEGIN
 12        IF p THEN
 13           dbms_output.put_line(n||' is true');
 14        ELSE
 15           dbms_output.put_line(n||' is false');
 16        END IF;
 17     END;
 18  BEGIN
 19     b1 := TRUE OR checkit;
 20     outp('b1',b1);
 21     b2 := checkit OR TRUE;
 22     outp('b2',b2);
 23  END;
 24  /

b1 is true
inside checkit
b2 is true

PL/SQL procedure successfully completed

SQL> 

请注意,OR 语句的结果取决于顺序。如果我先调用函数,那么无论其他项的值如何,都会执行该函数。似乎从左到右评估 OR 语句,直到获得 TRUE,此时处理停止并且结果为 TRUE。

我的问题是,这是我可以依赖的东西吗?或者这种行为会在未来的 PL/SQL 版本中改变吗?如果它可以改变,有没有办法强制评估我可以依赖的函数(不创建另一个变量并使用单独的赋值语句)?

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    是的。 PL/SQL 从左到右执行short circuit evaluation 的逻辑表达式。

    【讨论】:

    • 完美。正是我想要的!
    • 我的谷歌“pl/sql 完整布尔评估”给了我完全相同的链接。
    • 这是一个比我尝试过的更好的搜索:“PLSQL 强制评估”。谢谢!
    【解决方案2】:

    如果它可以改变,有没有办法强制评估我可以依赖的函数(无需创建另一个变量并使用单独的赋值语句)?

    如果您要求必须对函数进行评估,即使这样做在逻辑上是多余的,这意味着它执行的操作不是简单地返回 TRUE 或 FALSE,例如也许它会更新一张桌子。 PL/SQL 函数具有这样的“副作用”并不是很好的做法。

    【讨论】:

    • 一系列编辑功能。每个问题都会编辑消息并返回一个指示符是否应该跳过当前记录。跳过标志以 FALSE 开始,如果检查失败则设置为 TRUE。如果它通过任何特定检查,我不希望跳过标志重置为 FALSE。
    • 您可以将这些函数替换为带有标志的 IN OUT 参数的过程。如果任何检查失败,程序会将标志设置为 TRUE,但如果没有检查失败,则将其置之不理: l_flag := FALSE; do_check1 (l_flag); do_check2 (l_flag); do_check3 (l_flag);
    【解决方案3】:

    在文档中,它指出短路评估适用于 IF、CASE 和 CASE 表达式:我敢打赌,它也适用于您引用的示例,但在技术上并没有记录它这样做。可能值得就这种行为向 Oracle 提出罚单以确认它。

    【讨论】:

      【解决方案4】:

      这被称为“短路评估”,它是大多数语言的规范,including PL/SQL

      【讨论】:

        【解决方案5】:

        它从左到右计算 OR 语句,从右到左计算 AND 语句。我没有找到任何关于它的文档。

        【讨论】:

          【解决方案6】:

          “..and AND statements from right to left”到底是什么意思?
          这是来自 oracle 文档=>

          在以下示例中,请注意,当 valid 的值为 FALSE 时,无论 done 的值如何,整个表达式都会产生 FALSE:

          有效并完成

          您可以在以下示例中查看顺序:

          声明
          b1 布尔值;
          b2 布尔值;

          功能检查 (v NUMBER)
          返回布尔值

          开始
          DBMS_OUTPUT.put_line('内部检查:' || v);
          返回真;
          结束检查;

          PROCEDURE outp (n VARCHAR2, p BOOLEAN)

          开始
          如果 p
          那么
          DBMS_OUTPUT.put_line (n || '为真');
          其他
          DBMS_OUTPUT.put_line (n || '为假');
          结束如果;
          结束;
          开始
          b1 := checkit (1) AND checkit (2);
          outp ('b1', b1);
          b2 := checkit (3) AND checkit (4);
          outp ('b2', b2);
          结束;


          内部检查:1
          内部检查:2
          b1 是真的
          内部检查:3
          内部检查:4
          b2 是真的

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-11-05
            • 2015-09-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-05
            • 2012-02-22
            相关资源
            最近更新 更多