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

SQL:cerca in un elenco di colonne con un determinato valore (all'interno di una riga)

Questa non è una normale funzionalità del database. Tuttavia non sei la prima persona che ha chiesto questo, o qualcosa del genere.

La soluzione richiede due cose. Il primo è il dizionario dei dati; il database Oracle non supporta Reflection ma viene fornito con una serie di viste che ci forniscono metadati sui nostri oggetti di database. In questo caso abbiamo bisogno di user_tab_columns , che ci darà le colonne per una determinata tabella. La seconda cosa è l'SQL dinamico; questa è la capacità di assemblare una query SQL in fase di esecuzione e quindi eseguirla. Ci sono un paio di modi per farlo, ma di solito sono sufficienti i cursori di riferimento.

Il codice seguente è una prova di concetto. Richiede quattro parametri:

  1. il nome della tabella in cui vuoi cercare
  2. il nome della colonna chiave primaria di quella tabella
  3. il valore della chiave primaria a cui vuoi limitare
  4. il valore che vuoi cercare.

È grezzo, quindi potrebbe essere necessario modificarlo per riordinare l'output o per rendere il programma più flessibile.

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;
/

Come puoi vedere, l'SQL dinamico è difficile da leggere. È più difficile eseguire il debug :) Quindi è una buona idea avere un mezzo per mostrare l'affermazione finale.

Ad ogni modo, ecco i risultati:

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>