Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

SQL:Pesquise uma lista de colunas com um determinado valor (dentro de uma linha)


Esta não é uma parte normal da funcionalidade do banco de dados. No entanto, você não é a primeira pessoa que pediu isso, ou algo parecido.

A solução requer duas coisas. O primeiro é o dicionário de dados; o banco de dados Oracle não suporta Reflection, mas vem com um conjunto de visualizações que nos fornecem metadados sobre nossos objetos de banco de dados. Neste caso, precisamos de user_tab_columns , que nos dará as colunas de uma determinada tabela. A segunda coisa é o SQL dinâmico; essa é a capacidade de montar uma consulta SQL em tempo de execução e executá-la. Existem algumas maneiras de fazer isso, mas normalmente os cursores de referência são suficientes.

O código a seguir é uma prova de conceito. São necessários quatro parâmetros:
  1. o nome da tabela que você deseja pesquisar
  2. o nome da coluna de chave primária dessa tabela
  3. o valor da chave primária que você deseja restringir
  4. o valor que você deseja pesquisar.

Ele é rústico e pronto, então você pode precisar editá-lo para organizar a saída ou tornar o programa mais flexível.
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;
/

Como você pode ver, o SQL dinâmico é difícil de ler. É mais difícil de depurar :) Portanto, é uma boa ideia ter um meio de mostrar a declaração final.

De qualquer forma, aqui estão os resultados:
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>