Разширявайки отговора на GolezTrol, можете да използвате регулярни изрази, за да намалите значително броя на рекурсивните заявки, които правите:
select instr('SSSRNNSRSSR','R', 1, level)
from dual
connect by level <= regexp_count('SSSRNNSRSSR', 'R')
REGEXP_COUNT() връща броя на съвпаденията на шаблона, в този случай броя пъти R
съществува в SSSRNNSRSSR
. Това ограничава нивото на рекурсия до точния брой, от който се нуждаете.
INSTR() просто търси индекса на R във вашия низ. level
е дълбочината на рекурсията, но в този случай също е нивото th появата на низа, тъй като ограничихме до броя на необходимите рекурси.
Ако низът, който искате да изберете, е по-сложен, можете да използвате регулярни изрази и REGEXP_INSTR() вместо INSTR(), но ще е по-бавно (не много) и е ненужно, освен ако не се изисква.
Прост бенчмарк според заявката:
Двете решения на CONNECT BY показват, че използването на REGEXP_COUNT е с 20% по-бързо за низ с този размер.
SQL> set timing on
SQL>
SQL> -- CONNECT BY with REGEX
SQL> declare
2 type t__num is table of number index by binary_integer;
3 t_num t__num;
4 begin
5 for i in 1 .. 100000 loop
6 select instr('SSSRNNSRSSR','R', 1, level)
7 bulk collect into t_num
8 from dual
9 connect by level <= regexp_count('SSSRNNSRSSR', 'R')
10 ;
11 end loop;
12 end;
13 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:03.94
SQL>
SQL> -- CONNECT BY with filter
SQL> declare
2 type t__num is table of number index by binary_integer;
3 t_num t__num;
4 begin
5 for i in 1 .. 100000 loop
6 select pos
7 bulk collect into t_num
8 from ( select substr('SSSRNNSRSSR', level, 1) as character
9 , level as pos
10 from dual t
11 connect by level <= length('SSSRNNSRSSR') )
12 where character = 'R'
13 ;
14 end loop;
15 end;
16 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:04.80
Функцията за конвейерна таблица е доста по-бавна, макар че би било интересно да се види как се представя при големи низове с много съвпадения.
SQL> -- PIPELINED TABLE FUNCTION
SQL> declare
2 type t__num is table of number index by binary_integer;
3 t_num t__num;
4 begin
5 for i in 1 .. 100000 loop
6 select *
7 bulk collect into t_num
8 from table(string_indexes('SSSRNNSRSSR','R'))
9 ;
10 end loop;
11 end;
12 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:06.54