Tak więc chcesz przeprowadzić bezpłatne wyszukiwanie tekstu w swojej bazie danych w stylu Google. Można to zrobić, ale występ będzie Teh Suck! Google jest szybki, ponieważ ma indeksy w swoich indeksach, zduplikowane magazyny danych i ogólnie optymalizuje wszystko pod kątem dokładnie tego rodzaju wyszukiwania.
W każdym razie, oto dowód koncepcji przy użyciu dynamicznego SQL i słownika danych Oracle. Zwróć uwagę, że ograniczam kolumny do typu danych, które chcę wyszukać, tj. Ciągów.
SQL> set serveroutput on size unlimited
SQL> declare
2 dummy varchar2(1);
3 begin
4 for r in ( select table_name, column_name from user_tab_cols
5 where data_type in ('VARCHAR2', 'CHAR', 'CLOB') )
6 loop
7 begin
8 execute immediate 'select null from '||r.table_name
9 ||' where '||r.column_name||' like ''%&search_value%'' '
10 ||' and rownum = 1'
11 into dummy;
12 dbms_output.put_line('Found it in >>>'
13 ||r.table_name||'.'||r.column_name);
14 exception
15 when others then
16 -- bad practice ahoy!
17 null;
18 end;
19 end loop;
20 end;
21 /
Enter value for search_value: MAISIE
old 9: ||' where '||r.column_name||' like ''%&search_value%'' '
new 9: ||' where '||r.column_name||' like ''%MAISIE%'' '
Found it in >>>T23.NAME
PL/SQL procedure successfully completed.
SQL>
Bardziej niezawodna implementacja może wymagać obsługi wielkości liter, całych słów itp. Jeśli korzystasz z wersji 10g lub wyższej, wyrażenia regularne mogą być przydatne, ale połączenie wyrażeń regularnych i dynamicznego SQL jest… hmmm, interesujące perspektywa.
Powtarzam, że występ będzie Teh Suck! na dużym zbiorze danych. Dostrojenie jest praktycznie niemożliwe, ponieważ nie możemy zindeksować każdej kolumny, a już na pewno nie obsługujemy podobnych rozmytych dopasowań. Alternatywnym podejściem byłoby użycie XQuery do wygenerowania reprezentacji danych XML, a następnie użycie tekstu do ich indeksowania. Utrzymanie takiego repozytorium byłoby kosztownością, ale wysiłek byłby rozsądną inwestycją, jeśli potrzebujesz tej funkcji regularnie, szczególnie w środowisku produkcyjnym.
Możemy przeprowadzić szersze wyszukiwanie we wszystkich tabelach, do których mamy uprawnienia, używając all_tab_cols
zamiast.
for r in ( select owner, table_name, column_name from all_tab_cols
where data_type in ('VARCHAR2', 'CHAR', 'CLOB') )
Oczywiście musimy poprzedzić schemat właściciela w wygenerowanej instrukcji.
execute immediate 'select null from '||r.owner||'.'||r.table_name
||' where '||r.column_name||' like ''%