【问题标题】:Use Decode in Loop statement in Oracle PL/SQL在 Oracle PL/SQL 中使用 Decode in Loop 语句
【发布时间】:2020-08-03 12:21:49
【问题描述】:

我想在 oracle 的 Loop 语句中使用 decode 但无法这样做。这是我的查询

             for cur1 in
                    (
                         select distinct nvl(COVID_RISK_ZONE_NAME, 'No Data') "COVID_RISK_ZONE_NAME" from covid_daily_status
                    )
                    loop
                    VparaText:=VparaText||''''||cur1.COVID_RISK_ZONE_NAME||''' AS ' || '"'|| cur1.COVID_RISK_ZONE_NAME||'",';
                    
                    VselectText:=VselectText||'x."'||cur1.COVID_RISK_ZONE_NAME||'"'|| ' AS ' || '"'||
decode(cur1.covid_risk_zone_name, 'No Classification' , 'Market Opened', 'No Data', 'No Info Avlbl' , cur1.covid_risk_zone_name)||'",';

                    end loop;

                select SUBSTR(VparaText, 1, LENGTH(VparaText) - 1) into VparaTemp from dual;  
                
                select SUBSTR(VselectText, 1, LENGTH(VselectText) - 1) into VSelectTemp from dual;

我收到此错误:[Error] PLS-00204 (195: 106): PLS-00204: function or pseudo-column 'DECODE' may be used in a SQL statement only

为什么我不能在循环中使用解码。

【问题讨论】:

标签: sql string oracle stored-procedures plsql


【解决方案1】:

您可以使用case 代替decode(),或者使用from dual 技巧。但最重要的是,我认为您在这里不需要光标和循环。你可以使用字符串聚合得到你想要的结果:

select
    listagg(
        ''''
            || covid_risk_zone_name 
            || ''' as "' 
            || covid_risk_zone_name 
            || '"', 
        ', '
    ) into VparaText,
    listagg(
        'x."' 
            || covid_risk_zone_name 
            || '" as "' 
            || decode(covid_risk_zone_name, 'No Classification' , 'Market Opened', 'No Data', 'No Info Avlbl' , covid_risk_zone_name) 
            || '"', 
        ', ') into VselectText
from (
    select distinct nvl(covid_risk_zone_name, 'No Data') covid_risk_zone_name 
    from covid_daily_status
) t

请注意,子查询并非绝对必要(您可以改用listagg(distinct ...) - 但它避免了一次又一次地重复nvl() 表达式。

【讨论】:

    【解决方案2】:

    您需要将解码部分作为 SELECT INTO from DUAL 的一部分。你可以试试

    声明一个新变量VselectTextNew

    select VselectText ||'x."'|| cur1.COVID_RISK_ZONE_NAME||'"'|| ' AS ' || '"'|| decode(cur1.covid_risk_zone_name, 'No Classification' , 'Market Opened', 'No Data', 'No Info Avlbl' , cur1.covid_risk_zone_name)||'",' 
                    into VselectTextNew from dual;
    

    将最后一部分替换为新变量

    【讨论】:

    • 感谢,经过一些修改,我的查询现在可以正常工作了
    【解决方案3】:

    不幸的是,解码并不是一个真正的功能。它是一个表达式,不能在 PL/SQL 中使用。仅在 SQL 语句中。

    【讨论】:

    • 完全准确,但为什么“不幸”?我们现在有了 CASE,应该使用它。
    • 我喜欢解码和使用它,因为如果我需要多次检查相等性,它通常比 CASE 短。
    【解决方案4】:

    非常感谢 @GMB、@Roberto Hernandez 和 @akk0rd87 的帮助。 为了完成我的查询,我使用了@Roberto Hernandez 技巧,但他的查询必须修改,因为它总是给我字符串中循环的最后一部分,因为“select VselectText”总是重置我的字符串,所以不得不稍微修改一下。

    for cur1 in
                        (
                             select distinct nvl(COVID_RISK_ZONE_NAME, 'No Data') "COVID_RISK_ZONE_NAME" from covid_daily_status
                        )
                        loop
                        VparaText:=VparaText||''''||cur1.COVID_RISK_ZONE_NAME||''' AS ' || '"'|| cur1.COVID_RISK_ZONE_NAME||'",';
                        
                        select VselectText ||'x."'|| cur1.COVID_RISK_ZONE_NAME||'"'|| ' AS ' || '"'||
                         decode(cur1.covid_risk_zone_name, 'No Classification' , 'Market Opened', 'No Data', 'No Info Avlbl' , cur1.covid_risk_zone_name)||'",' 
                        into VselectTextNew from dual;
                        
                        vLong := vLong||VselectTextNew; --- Added new string.
                        
    
                        end loop;
    
                    select SUBSTR(VparaText, 1, LENGTH(VparaText) - 1) into VparaTemp from dual;  
                    
                    select SUBSTR(vLong, 1, LENGTH(vLong) - 1) into VSelectTemp from dual;
    

    我也会尝试@GMB 查询,因为我在直接使用查询时遇到了一些问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多