Oracle
 sql >> Database >  >> RDS >> Oracle

Selezione SQL per tutti i record che possono contenere un valore specifico

Quindi, vuoi eseguire una ricerca di testo gratuita simile a Google nel tuo database. Questo può essere fatto, ma la performance sarà Teh Suck! Google è veloce perché ha indici sui suoi indici, archivi di dati duplicati e generalmente ottimizza tutto proprio per questo tipo di ricerca.

Ad ogni modo, ecco una prova di concetto che utilizza SQL dinamico e il dizionario di dati Oracle. Nota che restringo le colonne al tipo di dati che voglio cercare, ad esempio stringhe.

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>

Un'implementazione più robusta potrebbe richiedere la gestione di maiuscole e minuscole, parole intere, ecc. Se sei su 10g o superiore, le espressioni regolari potrebbero essere utili, ma combinare regex e SQL dinamico è un, ehm, interessante potenziale cliente.

Ripeto che la performance sarà Teh Suck! su un grande set di dati. È praticamente impossibile ottimizzare, perché non possiamo indicizzare ogni colonna e certamente non supportare LIKE o corrispondenze fuzzy simili. Un approccio alternativo sarebbe utilizzare XQuery per generare una rappresentazione XML dei dati e quindi utilizzare Text per indicizzarli. Mantenere un tale repository sarebbe un sovraccarico, ma lo sforzo sarebbe un buon investimento se hai bisogno di questa funzionalità su base regolare, specialmente in un ambiente di produzione.

Possiamo condurre una ricerca più ampia su tutte le tabelle su cui abbiamo privilegi utilizzando all_tab_cols invece.

for r in ( select owner, table_name, column_name from all_tab_cols
                   where data_type in ('VARCHAR2', 'CHAR', 'CLOB') )

Ovviamente dobbiamo anteporre lo schema proprietario nell'istruzione generata.

execute immediate 'select null from '||r.owner||'.'||r.table_name
                       ||' where '||r.column_name||' like ''%