Het gebruik van dynamische SQL is de eenvoudigste benadering vanuit een coderingsstandpunt. Het probleem met dynamische SQL is echter dat je elke afzonderlijke versie van de query hard moet ontleden, wat niet alleen het potentieel heeft om je CPU te belasten, maar het potentieel heeft om je gedeelde pool te overspoelen met veel niet-deelbare SQL-instructies, waardoor out-instructies die u in de cache wilt opslaan, wat leidt tot meer harde parsen en fragmentatiefouten in de gedeelde pool. Als u dit eenmaal per dag uitvoert, is dat waarschijnlijk geen groot probleem. Als honderden mensen het duizenden keren per dag uitvoeren, is dat waarschijnlijk een grote zorg.
Een voorbeeld van de dynamische SQL-aanpak
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.
Als alternatief kunt u een verzameling gebruiken. Dit heeft het voordeel dat het een enkele, deelbare cursor genereert, zodat u zich geen zorgen hoeft te maken over het hard parseren of overstromen van de gedeelde pool. Maar het vereist waarschijnlijk wat meer code. De eenvoudigste manier om met collecties om te gaan
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.
Als je daarentegen echt moet beginnen met een door komma's gescheiden lijst met waarden, dan moet je die string in een verzameling ontleden voordat je hem kunt gebruiken. Er zijn verschillende manieren om een begrensde tekenreeks te ontleden -- mijn persoonlijke favoriet is het gebruik van reguliere expressies in een hiërarchische zoekopdracht, maar je zou zeker ook een procedurele benadering kunnen schrijven
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.