1

我有一个具有以下 pl/sql 块的存储过程。此块在 for 语句中使用 select 查询,但我需要将该静态变量更改为动态查询。当我改变它时,它有错误。有什么方法可以在隐式游标中使用 FOR LOOP 变量。

  declare
      sql_query varchar2(32767) := 'select ctlchar ';
      kpiNameQuery varchar2(600);
      isWg boolean := true;
    begin
          IF isWG then
             kpiNameQuery := 'select distinct KPI_NAME from weeklykpi where kpi_name in (select kpi_wg from auxillary.kpi_types) order by 1';

      Else
        kpiNameQuery := 'select distinct KPI_NAME from weeklykpi where kpi_name in (select kpi_wg1 from auxillary.kpi_types) order by 1';
      End IF;         

     for KPI_NAME in kpiNameQuery
      loop
          sql_query := sql_query || ' , min(case when KPI_NAME = '''||x.KPI_NAME||''' then KPI_VALUE end) as '||x.KPI_NAME;
          dbms_output.put_line(sql_query);
      end loop;
end;
4

2 回答 2

1

不幸的是,文档指出

如果动态 SQL 语句是返回多行的 SELECT 语句,则本机动态 SQL 为您提供以下选择:

  • 使用带有 BULK COLLECT INTO 子句的 EXECUTE IMMEDIATE 语句。
  • 使用 OPEN FOR、FETCH 和 CLOSE 语句。

因此,您将不得不使用 REF 游标(或EXECUTE IMMEDIATE遍历结果)。

顺便说一句,在您的情况下,您可以使用静态 SQL 并具有相当的性能:

BEGIN
   FOR cc IN (SELECT DISTINCT KPI_NAME
                FROM weeklykpi
               WHERE kpi_name IN (SELECT CASE WHEN l_variable = 1
                                                  THEN kpi_wg
                                              ELSE kpi_wg1
                                         END
                                    FROM auxillary.kpi_types) LOOP
               ORDER BY 1
      -- do something
   END LOOP;
END;

您必须使用除布尔值之外的其他类型,因为 SQL 不知道它。

于 2012-11-16T10:08:34.327 回答
1

您可以使用以下光标实现类似的功能

declare
      type t_cursor is ref cursor;
      c_cursor t_cursor;
      l_sql varchar2(512);
      l_var number;
   begin
     l_sql := 'select count(*) from emp';  -- do dynamic check before here for    
   -- correct sql
     open c_cursor for l_sql;
     loop
       fetch c_cursor 
        into l_var;           
       exit When c_cursor%notfound;
       DBMS_OUTPUT.put_line ('val '||l_var);           
     end loop;  
     close c_cursor;
  end; 
于 2012-11-16T10:10:01.713 回答