Memperluas jawaban GolezTrol, Anda dapat menggunakan ekspresi reguler untuk secara signifikan mengurangi jumlah kueri rekursif yang Anda lakukan:
select instr('SSSRNNSRSSR','R', 1, level)
from dual
connect by level <= regexp_count('SSSRNNSRSSR', 'R')
REGEXP_COUNT() mengembalikan berapa kali pola cocok, dalam hal ini berapa kali R
ada di SSSRNNSRSSR
. Ini membatasi tingkat rekursi ke jumlah persis yang Anda butuhkan.
INSTR() cukup mencari indeks R di string Anda. level
adalah kedalaman rekursi tetapi dalam hal ini juga level th kemunculan string karena kami membatasi jumlah pengulangan yang diperlukan.
Jika string yang ingin Anda pilih lebih rumit, Anda bisa menggunakan ekspresi reguler dan REGEXP_INSTR() sebagai lawan INSTR() tetapi akan lebih lambat (tidak terlalu banyak) dan tidak perlu kecuali diperlukan.
Tolok ukur sederhana seperti yang diminta:
Dua solusi CONNECT BY akan menunjukkan bahwa menggunakan REGEXP_COUNT 20% lebih cepat pada string dengan ukuran ini.
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
Fungsi tabel pipelined agak lebih lambat, meskipun akan menarik untuk melihat bagaimana kinerjanya pada string besar dengan banyak kecocokan.
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