Oracle
 sql >> Datenbank >  >> RDS >> Oracle

SQL-Auswahl für alle Datensätze, die einen bestimmten Wert enthalten können

Sie möchten also eine Google-ähnliche Freitextsuche über Ihre Datenbank durchführen. Dies kann getan werden, aber die Aufführung wird Teh Suck! Google ist schnell, weil es Indizes in seinen Indizes hat, Daten doppelt speichert und generell alles für genau diese Art von Suche optimiert.

Wie auch immer, hier ist ein Proof of Concept mit dynamischem SQL und dem Oracle Data Dictionary. Beachten Sie, dass ich die Spalten auf den Datentyp beschränke, nach dem ich suchen möchte, z. B. Zeichenfolgen.

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>

Eine robustere Implementierung muss möglicherweise Groß-/Kleinschreibung, ganze Wörter usw. handhaben. Wenn Sie 10 g oder höher verwenden, könnten reguläre Ausdrücke nützlich sein, aber die Kombination von Regex und dynamischem SQL ist ein, äh, interessant Interessent.

Ich wiederhole, diese Aufführung wird Teh Suck! auf einem großen Datensatz. Es ist praktisch unmöglich zu tunen, da wir nicht jede Spalte indizieren können und schon gar nicht LIKE oder ähnliche Fuzzy-Matches unterstützen. Ein alternativer Ansatz wäre, XQuery zu verwenden, um eine XML-Darstellung Ihrer Daten zu generieren und sie dann mit Text zu indizieren. Die Pflege eines solchen Repositorys wäre ein Overhead, aber der Aufwand wäre eine gute Investition, wenn Sie diese Funktionalität regelmäßig benötigen, insbesondere in einer Produktionsumgebung.

Mit all_tab_cols können wir eine umfassendere Suche über alle Tabellen hinweg durchführen, für die wir Berechtigungen haben stattdessen.

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

Offensichtlich müssen wir das besitzende Schema in der generierten Anweisung voranstellen.

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