Så du vil lave en Google-lignende fritekstsøgning over din database. Dette kan lade sig gøre, men forestillingen vil være Teh Suck! Google er hurtig, fordi den har indekser på sine indekser, dublerede datalagre og generelt optimerer alt til netop denne form for søgning.
Uanset hvad, her er et proof of concept ved hjælp af dynamisk SQL og Oracle-dataordbogen. Bemærk, at jeg begrænser kolonnerne til den type data, jeg vil søge efter, dvs. strenge.
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>
En mere robust implementering skal muligvis håndtere store og små bogstaver, hele ord osv. Hvis du er på 10g eller højere, kan regulære udtryk være nyttige, men at kombinere regex og dynamisk SQL er en, eh, interessant udsigt.
Jeg gentager, at forestillingen bliver Teh Suck! på et stort datasæt. Det er praktisk talt umuligt at tune, fordi vi ikke kan indeksere hver kolonne, og bestemt ikke for at understøtte LIKE eller lignende fuzzy matches. En alternativ tilgang ville være at bruge XQuery til at generere en XML-repræsentation af dine data og derefter bruge Tekst til at indeksere dem. At vedligeholde et sådant lager ville være overhead, men indsatsen ville være en god investering, hvis du har brug for denne funktionalitet på regelmæssig basis, især i et produktionsmiljø.
Vi kan udføre en bredere søgning på tværs af alle de tabeller, vi har privilegier på, ved at bruge all_tab_cols
i stedet.
for r in ( select owner, table_name, column_name from all_tab_cols
where data_type in ('VARCHAR2', 'CHAR', 'CLOB') )
Det er klart, at vi er nødt til at præfikse ejerskemaet i den genererede sætning.
execute immediate 'select null from '||r.owner||'.'||r.table_name
||' where '||r.column_name||' like ''%