【问题标题】:Conditional strings in plsql like sprintfplsql 中的条件字符串,如 sprintf
【发布时间】:2016-09-08 01:58:00
【问题描述】:

写下面的代码给了我错误提示:

PL/SQL:语句被忽略 PLS-00382:表达式类型错误:

代码:

    if ( l_vol = 0 ) 
    then 
        l_cndtn_string := 'l_wgt > l_wgt_limit';            
    else
        l_cndtn_string := '(l_wgt > l_wgt_limit) and (l_vol > l_vol_limit)';
    end if;

    if ( l_cndtn_string )
    then
        l_isis_task := 'PO';
    else
        l_isis_task := 'TO';
    end if;

【问题讨论】:

    标签: plsql


    【解决方案1】:

    If statement 计算 boolean expression。在你的例子中

    if ( l_cndtn_string )
    

    l_cndtn_string 不是布尔表达式,而是character expression,它们之间没有隐式转换。

    请自行检查Expressions

    我不知道您的逻辑是什么,但以下示例向您展示了一种将字符表达式转换为布尔表达式的方法:

    if l_cndtn_string is not null -- a boolean expression
    then
      null;
    else
      null;
    end if;
    

    【讨论】:

      【解决方案2】:

      您想要动态条件构建。在plsql,和其他编译语言一样,很难做到。

      试试这样:

      if ( l_vol = 0 ) 
      then 
          if(l_wgt > l_wgt_limit) then
            l_isis_task := 'PO';
          end if;           
      else
          if(l_wgt > l_wgt_limit and l_vol > l_vol_limit) then
            l_isis_task := 'TO'; 
          end if;
      end if;
      

      【讨论】:

        【解决方案3】:

        IF 之后是布尔表达式,而不是字符串 - 这就是您收到 PLS-00382 错误的原因。您当然可以尝试使用动态 sql 动态评估您的表达式,但实际上您想要的很简单:

        if ( l_wgt > l_wgt_limit and ( l_vol = 0 or l_vol > l_vol_limit ) )
        then
            l_isis_task := 'PO';
        else
            l_isis_task := 'TO';
        end if;
        

        【讨论】:

          【解决方案4】:

          哦,只有在阅读其他答案后,我才意识到这个问题是关于什么的。我决定也保留我原来的答案,因为关于 if 语句中字符表达的观点仍然正确。

          其他答案是正确的,即使用动态 PL/SQL 构建基于字符串评估的逻辑通常不是一个好主意。他们也提出了正确的解决方案,但恕我直言,存在更好的方法。

          通常当我在 PL/SQL 中有多个条件时,我会为条件命名。请参阅下面说明该技术的示例。这些名称使代码能够自我记录,并且极大地提高了代码的可读性,就像现在通常将条件读取为人类语言一样。

          declare
            v_volume number := 0;
            v_weight number := 1;
          
            v_weight_limit constant number := 10;
            v_volume_limit constant number := 10;
          
            v_has_volume constant boolean := v_volume > 0;
            v_exceed_weight_limit constant boolean := v_weight > v_weight_limit;
            v_exceed_volume_limit constant boolean := v_volume > v_volume_limit;
          begin
            -- no guarantee the logic is the same than in question
            -- but just illustrates the coding style
            if  v_has_volume
            and v_exceed_weight_limit
            and v_exceed_volume_limit
            then
              null; -- something
            else
              null; -- something else
            end if;
          end;
          /
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-07-04
            • 2018-06-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-02-10
            • 1970-01-01
            相关资源
            最近更新 更多