Korzystanie z dynamicznego SQL jest najprostszym podejściem z punktu widzenia kodowania. Problem z dynamicznym SQL polega jednak na tym, że musisz ciężko analizować każdą odrębną wersję zapytania, która nie tylko może obciążać Twój procesor, ale może również zalać pulę współdzieloną wieloma nieudostępnianymi instrukcjami SQL. out instrukcji, które chcesz buforować, powodując więcej twardych analiz i błędów fragmentacji puli współdzielonej. Jeśli uruchamiasz to raz dziennie, prawdopodobnie nie jest to poważny problem. Jeśli setki ludzi wykonują to tysiące razy dziennie, jest to prawdopodobnie poważny problem.
Przykład dynamicznego podejścia 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.
Alternatywnie możesz użyć kolekcji. Ma to tę zaletę, że generuje pojedynczy, współużytkowany kursor, dzięki czemu nie musisz się martwić trudną analizą lub zalaniem współdzielonej puli. Ale prawdopodobnie wymaga to trochę więcej kodu. Najprostszy sposób radzenia sobie z kolekcjami
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.
Z drugiej strony, jeśli naprawdę musisz zacząć od listy wartości oddzielonych przecinkami, będziesz musiał przeanalizować ten ciąg w kolekcję, zanim będziesz mógł go użyć. Istnieją różne sposoby analizowania rozdzielanego ciągu — moim osobistym ulubionym jest używanie wyrażeń regularnych w zapytaniach hierarchicznych, ale z pewnością można też napisać podejście proceduralne
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.