Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Zapytanie Oracle, aby znaleźć wszystkie wystąpienia znaku w ciągu znaków

Rozszerzając odpowiedź GolezTrol możesz użyć wyrażeń regularnych, aby znacznie zmniejszyć liczbę wykonywanych zapytań rekurencyjnych:

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

REGEXP_COUNT() zwraca liczbę dopasowań wzorca, w tym przypadku liczbę razy R istnieje w SSSRNNSRSSR . Ogranicza to poziom rekurencji do dokładnie takiej liczby, jakiej potrzebujesz.

INSTR() po prostu wyszukuje indeks R w Twoim łańcuchu. level to głębokość rekurencji, ale w tym przypadku jest to również poziom tego wystąpienie ciągu, ponieważ ograniczyliśmy się do wymaganej liczby rekurencji.

Jeśli ciąg, który chcesz wybrać, jest bardziej skomplikowany, możesz użyć wyrażeń regularnych i REGEXP_INSTR() w przeciwieństwie do INSTR(), ale będzie to wolniejsze (niewiele) i jest niepotrzebne, chyba że jest to wymagane.

Prosty test porównawczy zgodnie z żądaniem:

Dwa rozwiązania CONNECT BY wskazują, że użycie REGEXP_COUNT jest o 20% szybsze w przypadku łańcucha o tym rozmiarze.

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

Funkcja tabeli potokowej jest nieco wolniejsza, chociaż byłoby interesujące zobaczyć, jak działa na dużych ciągach z dużą liczbą dopasowań.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nie ważny miesiąc na wyciągu INSERT

  2. Zrozumienie różnic między Table a Transaction API

  3. Oracle usuwa wiersze z wielu tabel

  4. Porady dotyczące korzystania z tabeli przestawnej w Oracle

  5. java.lang.UnsatisfiedLinkError:brak ocijdbc11 w javie. biblioteka.ścieżka