【问题标题】:How to prevent Oracle to use short circuit in PL/SQL如何防止Oracle在PL/SQL中使用短路
【发布时间】:2016-01-01 02:07:28
【问题描述】:

以下 PL/SQL 代码显示了函数 ensure(...) 以及我将如何在 Oracle 11g 中使用它。

declare
valid boolean;
function ensure(b boolean, failure_message varchar) return boolean is begin
  if not b then
    dbms_output.put_line(failure_message);
    return false;
  else
    return true;
  end if;
end ensure;
begin
  valid := true;
  valid := valid 
        and ensure(1=1, 'condition 1 failed') 
        and ensure(1=2, 'condition 2 failed') 
        and ensure(2=3, 'condition 3 failed');

  if not valid then
    dbms_output.put_line('some conditions failed, terminate the program');
    return;
  end if;

  dbms_output.put_line('do the work');
end;
/

我想使用ensure(...)来预验证一组条件,只有所有条件都通过后,程序才允许工作。

我希望程序评估每个 ensure(...),即使前面的 ensure(...) 返回 false,以便为每个失败的条件打印 failure_message

问题在于 Oracle 使用短路评估并忽略返回 false 之后的其余条件。例如,上面的程序打印以下消息。

condition 2 failed
some conditions failed, terminate the program

如何告诉 Oracle 不使用短路评估,以便上述程序打印以下消息。

condition 2 failed
condition 3 failed
some conditions failed, terminate the program

【问题讨论】:

  • 当你使用函数时,最好从面向函数的编程角度来考虑;即一个函数应该没有副作用;它是否被执行并不重要。如果你需要一个动作发生,它应该作为一个过程运行,而不是作为一个函数。

标签: plsql oracle11g short-circuiting


【解决方案1】:

试试:

declare
valid boolean;
con1 boolean;
con2 boolean;
con3 boolean;
function ensure(b boolean, failure_message varchar) return boolean is begin
  if not b then
    dbms_output.put_line(failure_message);
    return false;
  else
    return true;
  end if;
end ensure;
begin
  valid := true;
  con1 := ensure(1=1, 'condition 1 failed') ;
  con2 := ensure(1=2, 'condition 2 failed') ;
  con3 := ensure(2=3, 'condition 3 failed');
  valid := con1 AND con2 AND con3;
  if not valid then
    dbms_output.put_line('some conditions failed, terminate the program');
    return;
  end if;

  dbms_output.put_line('do the work');
end;
/

【讨论】:

    【解决方案2】:

    我通常使用assertions 验证先决条件。我不知道这是否适合 OP 的情况,但我认为作为可行的解决方案替代方案值得一提。

    示例:

    declare
      procedure assert(p_cond in boolean, p_details in varchar2 default null) is
      begin
        if not p_cond then
          raise_application_error(-20100, p_details);
        end if;
      end;
    begin
      assert(1 = 1, 'first');
      assert(1 = 2, 'second');
      assert(1 = 1, 'third');
    
      -- all preconditions are valid, processing is "safe"
    end;
    /
    

    显然,在实际代码/逻辑中,必须考虑应如何处理异常。也可能使用/需要状态变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-07
      • 2012-08-30
      • 2021-08-15
      • 1970-01-01
      • 2021-09-11
      • 2012-04-22
      • 1970-01-01
      相关资源
      最近更新 更多