從編碼的角度來看,使用動態SQL是最簡單的方法。然而,動態SQL的問題在於,你必須努力解析查詢的每個不同版本,這不僅可能會導致CPU處理稅,而且有可能會用大量不可共享的SQL語句淹沒共享池,推動你想要緩存的聲明,導致更多的硬解析和共享池碎片錯誤。如果你每天運行一次,這可能不是一個主要問題。如果數百人每天執行數千次,那可能是一個主要問題。
動態SQL方法
SQL> ed
Wrote file afiedt.buf
1 declare
2 l_deptnos varchar2(100) := '10,20';
3 l_rc sys_refcursor;
4 l_dept_rec dept%rowtype;
5 begin
6 open l_rc for 'select * from dept where deptno in (' || l_deptnos || ')';
7 loop
8 fetch l_rc into l_dept_rec;
9 exit when l_rc%notfound;
10 dbms_output.put_line(l_dept_rec.dname);
11 end loop;
12 close l_rc;
13* end;
SQL>/
ACCOUNTING
RESEARCH
PL/SQL procedure successfully completed.
交替的例子,你可以使用一個集合。這具有生成單個可共享遊標的優勢,因此您不必擔心硬解析或泛洪共享池。但它可能需要更多的代碼。爲處理集合最簡單的方法
SQL> ed
Wrote file afiedt.buf
1 declare
2 l_deptnos tbl_deptnos := tbl_deptnos(10,20);
3 begin
4 for i in (select *
5 from dept
6 where deptno in (select column_value
7 from table(l_deptnos)))
8 loop
9 dbms_output.put_line(i.dname);
10 end loop;
11* end;
SQL>/
ACCOUNTING
RESEARCH
PL/SQL procedure successfully completed.
如果,另一方面,你真的要開始用逗號分隔值的列表中,那麼你將有該字符串解析爲一個集合纔可以使用它。有多種方法來解析分隔string--我個人最喜歡的是在分層查詢使用正則表達式,但你當然可以寫一個程序的方法,以及
SQL> ed
Wrote file afiedt.buf
1 declare
2 l_deptnos tbl_deptnos;
3 l_deptno_str varchar2(100) := '10,20';
4 begin
5 select regexp_substr(l_deptno_str, '[^,]+', 1, LEVEL)
6 bulk collect into l_deptnos
7 from dual
8 connect by level <= length(replace (l_deptno_str, ',', NULL));
9 for i in (select *
10 from dept
11 where deptno in (select column_value
12 from table(l_deptnos)))
13 loop
14 dbms_output.put_line(i.dname);
15 end loop;
16* end;
17/
ACCOUNTING
RESEARCH
PL/SQL procedure successfully completed.
你可以看到我的答案(或任何你喜歡的。)在http://stackoverflow.com/a/18100419/947356 我希望這會幫助你。 – Sergey