2012-11-16 52 views
1

我有一個具有以下pl/sql塊的存儲過程。該塊在for語句中使用select查詢,但我需要將該靜態變量更改爲動態查詢。當我改變它有錯誤。在隱式遊標中有沒有辦法在FOR LOOP中使用變量。用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; 

回答

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; 
+0

我應該關閉光標嗎? – kinkajou

+0

@Kitex我已經更新了我的答案。 – user75ponic

1

Unfotunately沒有,the doc states

如果動態SQL語句返回多個行的SELECT語句,本地動態SQL給你以下選擇:

  • 使用EXECUTE IMMEDIATE語句與BULK COLLECT INTO子句。
  • 使用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。

+0

非常謝謝!以及我最終使用顯式光標,但你所說的技術很好。感謝您的更多信息! – kinkajou