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

SQL:Durchsuchen einer Liste von Spalten mit einem bestimmten Wert (innerhalb einer Zeile)

Dies ist keine normale Datenbankfunktionalität. Sie sind jedoch nicht die erste Person, die danach gefragt hat, oder so ähnlich.

Die Lösung erfordert zwei Dinge. Das erste ist das Datenwörterbuch; Die Oracle-Datenbank unterstützt Reflection nicht, enthält jedoch eine Reihe von Ansichten, die uns Metadaten zu unseren Datenbankobjekten liefern. In diesem Fall benötigen wir user_tab_columns , wodurch wir die Spalten für eine bestimmte Tabelle erhalten. Die zweite Sache ist dynamisches SQL; dies ist die Möglichkeit, eine SQL-Abfrage zur Laufzeit zusammenzustellen und dann auszuführen. Es gibt ein paar Möglichkeiten, dies zu tun, aber normalerweise reichen Ref-Cursor aus.

Der folgende Code ist ein Machbarkeitsnachweis. Es benötigt vier Parameter:

  1. Name der zu durchsuchenden Tabelle
  2. der Name der Primärschlüsselspalte dieser Tabelle
  3. der Primärschlüsselwert, nach dem Sie einschränken möchten
  4. der Wert, nach dem Sie suchen möchten.

Es ist grob und fertig, so dass Sie es möglicherweise bearbeiten müssen, um die Ausgabe aufzuräumen oder das Programm flexibler zu machen.

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, ein Mittel zu haben, um die endgültige 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>