Ved at udvide GolezTrols svar kan du bruge regulære udtryk til markant at reducere antallet af rekursive forespørgsler, du laver:
select instr('SSSRNNSRSSR','R', 1, level)
from dual
connect by level <= regexp_count('SSSRNNSRSSR', 'R')
REGEXP_COUNT() returnerer antallet af gange mønsteret matcher, i dette tilfælde antallet af gange R
findes i SSSRNNSRSSR
. Dette begrænser niveauet af rekursion til det nøjagtige antal, du skal.
INSTR() søger blot efter indekset for R i din streng. level
er dybden af rekursionen, men i dette tilfælde er det også niveauet th forekomst af strengen, da vi begrænsede til antallet af krævede gentagelser.
Hvis den streng, du vil udvælge, er mere kompliceret, kan du vælge regulære udtryk og REGEXP_INSTR() i modsætning til INSTR(), men det vil være langsommere (ikke meget), og det er unødvendigt, medmindre det er nødvendigt.
Simpel benchmark som anmodet:
De to CONNECT BY-løsninger indikerer, at brugen af REGEXP_COUNT er 20 % hurtigere på en streng af denne størrelse.
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
Den pipelinede tabelfunktion er en del langsommere, selvom det ville være interessant at se, hvordan den klarer sig over store strenge med mange matches.
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