我有一个存储过程,其中包含以下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;
答案 0 :(得分:1)
不幸的是,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不知道。
答案 1 :(得分: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;