Plsql 使用for循环打开隐式游标

Plsql 使用for循环打开隐式游标,plsql,oracle11g,Plsql,Oracle11g,我有一个具有以下pl/sql块的存储过程。该块在for语句中使用select查询,但我需要将该静态变量更改为动态查询。因为我改变了,它有错误。有没有办法在隐式游标中使用带有FOR循环的变量 declare sql_query varchar2(32767) := 'select ctlchar '; kpiNameQuery varchar2(600); isWg boolean := true; begin IF isWG t

我有一个具有以下pl/sql块的存储过程。该块在for语句中使用select查询,但我需要将该静态变量更改为动态查询。因为我改变了,它有错误。有没有办法在隐式游标中使用带有FOR循环的变量

  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;
不切实际的不,:

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

  • 将EXECUTE IMMEDIATE语句与BULK COLLECT INTO子句一起使用
  • 使用OPEN FOR、FETCH和CLOSE语句
因此,您必须使用REF游标(或
立即执行
并在结果上循环)

顺便说一句,在您的情况下,您可以使用静态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不知道它。

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

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; 

非常感谢!我最终使用了显式游标,但你说的十项技术很好。感谢您提供更多信息!