Dies ist kein normaler Teil der Datenbankfunktionalität. Sie sind jedoch nicht die erste Person, die dies oder etwas Ähnliches verlangt hat.
Die Lösung erfordert zwei Dinge. Das erste ist das Datenwörterbuch; die Oracle-Datenbank unterstützt Reflection nicht, aber sie verfügt über eine Reihe von Ansichten, die uns Metadaten über unsere Datenbankobjekte liefern. In diesem Fall benötigen wir user_tab_columns
, die uns die Spalten einer bestimmten Tabelle liefert. Der zweite Punkt ist dynamisches SQL, d.h. die Möglichkeit, eine SQL-Abfrage zur Laufzeit zusammenzustellen und dann auszuführen. Es gibt mehrere Möglichkeiten, dies zu tun, aber in der Regel sind Ref-Cursor ausreichend.
Der folgende Code ist ein Beispiel für ein Konzept. Er benötigt vier Parameter:
- den Namen der Tabelle, die Sie durchsuchen möchten
- der Name des Primärschlüssels dieser Tabelle Spalte
- den Primärschlüsselwert, den Sie einschränken wollen
- den Wert, nach dem Sie suchen möchten.
Es handelt sich um eine Rohfassung, die Sie möglicherweise noch bearbeiten müssen, um die Ausgabe zu optimieren oder das Programm flexibler zu gestalten.
create or replace procedure search_cols
(tname in user_tables.table_name%type
, pk_col in user_tab_columns.column_name%type
, pk in number
, val in number )
is
firstcol boolean := true;
stmt varchar2(32767);
result varchar2(32767);
rc sys_refcursor;
begin
stmt := 'select ';
<< projection >>
for lrec in ( select column_name from user_tab_columns
where table_name = tname
and column_name != pk_col
and data_type = 'NUMBER'
order by column_id )
loop
if not firstcol then
stmt := stmt || chr(10) || '||'',''||';
else
firstcol := false;
end if;
stmt := stmt || ' case when '|| lrec.column_name||' = '|| val ||
' then '''|| lrec.column_name || ''' else null end';
end loop projection;
stmt := stmt || chr(10)|| ' from '||tname||' where '|| pk_col || ' = '|| pk;
-- dbms_output.put_line(stmt);
open rc for stmt;
fetch rc into result;
close rc;
dbms_output.put_line(tname || '::' || val || ' found in '||result);
end search_cols;
/
Wie Sie sehen können, ist dynamisches SQL schwer zu lesen. Es ist schwieriger zu debuggen :) Daher ist es eine gute Idee, eine Möglichkeit zu haben, die letzte Anweisung anzuzeigen.
Wie auch immer, hier sind die Ergebnisse:
SQL> set serveroutput on size unlimited
SQL> exec search_cols('T23', 'ID', 111, 10)
T23::10 found in ,COL_B,COL_C,
PL/SQL procedure successfully completed.
SQL> exec search_cols('T23', 'ID', 222, 10)
T23::10 found in COL_A,,,
PL/SQL procedure successfully completed.
SQL>