Как сравнить элементы в массиве с элементами в столбце базы данных с помощью регулярных выражений?

Я пытаюсь получить список элементов в массиве следующим образом:

['GRADE', 'GRATE', 'GRAPE', /*About 1000 other entries here ...*/ ]

и сопоставьте их с их вхождениями в столбце базы данных Oracle, заполненной такими записями:

1|'ANTERIOR'
2|'ANTEROGRADE'
3|'INGRATE'
4|'RETROGRADE'
5|'REIGN'
...|...
/*About 1,000,000 other entries here*/

Для каждой записи в этом массиве слов G я хотел бы пройтись по столбцу слов базы данных Oracle и попытаться найти правосторонние совпадения для каждой записи в массиве. В этом примере все записи 2, 3 и 4 в базе данных будут совпадать.

На любом другом языке программирования это выглядело бы примерно так:

for entry in array:
  for each in column:
    if entry.right_match(each):
      print entry

Как это сделать в PL/SQL?


person duber    schedule 23.07.2013    source источник


Ответы (1)


В PL/SQL это можно сделать так:

declare
   SUBTYPE my_varchar2_t IS varchar2( 100 );
   TYPE Roster IS TABLE OF my_varchar2_t;  
   names Roster := Roster( 'GRADE', 'GRATE', 'GRAPE');
begin
  FOR c IN ( SELECT id, name FROM my_table )
  LOOP
      FOR i IN names.FIRST .. names.LAST LOOP 
         IF regexp_like( c.name,   names( i )  ) THEN
              DBMS_OUTPUT.PUT_LINE( c.id || '  ' || c.name );
         END IF;
      END LOOP;
  END LOOP;
end;
/

но это построчная обработка, для большой таблицы это было бы очень медленно.

Я думаю, что было бы лучше сделать это так, как показано ниже:

create table test123 as
select 1 id ,'ANTERIOR' name from dual union all
select 2,'ANTEROGRADE' from dual union all
select 3,'INGRATE' from dual union all
select 4,'RETROGRADE' from dual union all
select 5,'REIGN' from dual ;

create type my_table_typ is table of varchar2( 100 );
/

select *
from table( my_table_typ( 'GRADE', 'GRATE', 'GRAPE' )) x
join test123 y on regexp_like( y.name, x.column_value ) 
;

COLUMN_VALUE  ID         NAME      
------------- ---------- -----------
GRADE                  2 ANTEROGRADE 
GRATE                  3 INGRATE     
GRADE                  4 RETROGRADE
person krokodilko    schedule 23.07.2013
comment
Д-н! Ты подтолкнул меня на это! Единственное, что я бы добавил, это некоторый синтаксис регулярного выражения, например. REGEXP_LIKE (y.name, x.column_value || '$') для соответствия только в конце. - person Andrew Wolfe; 23.07.2013
comment
Используйте имя LIKE '%'|| значение вместо REGEXP_LIKE, LIKE немного быстрее. - person krokodilko; 23.07.2013
comment
Кроме того, для ускорения поиска можно использовать индекс на основе функций, как описано здесь. - person ThinkJet; 23.07.2013