sql >> Database >  >> RDS >> Oracle

Oracle-query om alle exemplaren van een teken in een tekenreeks te vinden

Door het antwoord van GolezTrol uit te breiden, kunt u reguliere expressies gebruiken om het aantal recursieve zoekopdrachten dat u doet aanzienlijk te verminderen:

 select instr('SSSRNNSRSSR','R', 1, level)
   from dual
connect by level <= regexp_count('SSSRNNSRSSR', 'R')

REGEXP_COUNT() retourneert het aantal keren dat het patroon overeenkomt, in dit geval het aantal keren R bestaat in SSSRNNSRSSR . Dit beperkt het recursieniveau tot het exacte aantal dat nodig is.

INSTR() zoekt eenvoudig naar de index van R in je string. level is de diepte van de recursie, maar in dit geval is het ook het niveau de voorkomen van de tekenreeks omdat we het aantal vereiste herhalingen hebben beperkt.

Als de string die je wilt uitkiezen ingewikkelder is, kun je voor reguliere expressies ans REGEXP_INSTR() gaan in plaats van INSTR(), maar het zal langzamer zijn (niet veel) en het is niet nodig tenzij nodig.

Eenvoudige benchmark zoals gevraagd:

De twee CONNECT BY-oplossingen geven aan dat het gebruik van REGEXP_COUNT 20% sneller is voor een string van deze omvang.

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

De pijplijn-tabelfunctie is een stuk langzamer, hoewel het interessant zou zijn om te zien hoe deze presteert over grote reeksen met veel overeenkomsten.

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


  1. Hoe kan ik in SQL Server een enkele rij vergrendelen op een manier die vergelijkbaar is met SELECT FOR UPDATE WAIT van Oracle?

  2. SQLite-volgorde op datum1530019888000

  3. ST_DWithin neemt parameter als graad, niet als meter, waarom?

  4. Waarde van weergave-item invullen bij query in Oracle Forms