此脚本不依赖统计信息。
在编写 PLSQL 的时候,我们应该尽量避免 LOOP 套 LOOP,因为双层循环,最内层循环类似笛卡儿积。假设外层循环返回 1 000 行数据,内层循环返回 1 000 行数据,那么内层循环里面的代码就会执行 1000*1000 次。以下脚本可以抓出 LOOP 套 LOOP 的 PLSQL。
with x as(select /*+ materialize */ owner,name,type,line,text,rownum rn from dba_source where (upper(text) like '%END%LOOP%' or upper(text) like '%FOR%LOOP%'))select a.owner,a.name,a.type from x a,x bwhere ((upper(a.text) like '%END%LOOP%'and upper(b.text) like '%END%LOOP%'and a.rn+1=b.rn)or (upper(a.text) like '%FOR%LOOP%'and upper(b.text) like '%FOR%LOOP%'and a.rn+1=b.rn))and a.owner=b.ownerand a.name=b.nameand a.type=b.typeand a.owner='SCOTT';
我们在 Scott 账户中创建 LOOP 套 LOOP 的存储过程。
create or replace procedure p_99 isbeginfor i in 1 .. 9 loopdbms_output.put_line('');for x in 1 .. 9 loopif (i >= x) thendbms_output.put(' ' || i || ' x ' || x || ' = ' || i * x);end if;end loop;dbms_output.put_line('');end loop;end;
我们通过脚本将以上的存储过程抓出。
with x as(select /*+ materialize */ owner,name,type,line,text,rownum rn from dba_sourcewhere (upper(text) like '%END%LOOP%' or upper(text) like '%FOR%LOOP%'))select distinct a.owner,a.name,a.type from x a,x bwhere ((upper(a.text) like '%END%LOOP%'and upper(b.text) like '%END%LOOP%'and a.rn+1=b.rn)or (upper(a.text) like '%FOR%LOOP%'and upper(b.text) like '%FOR%LOOP%'and a.rn+1=b.rn))and a.owner=b.ownerand a.name=b.nameand a.type=b.typeand a.owner='SCOTT';
OWNER NAME TYPE--------------- --------------- ---------------SCOTT P_99 PROCEDURE
