sql >> Base de Datos >  >> RDS >> Oracle

SQL:busque una lista de columnas con un valor dado (dentro de una fila)

Esta no es una parte normal de la funcionalidad de la base de datos. Sin embargo, no eres la primera persona que ha pedido esto, o algo parecido.

La solución requiere dos cosas. El primero es el diccionario de datos; la base de datos de Oracle no es compatible con Reflection, pero viene con un conjunto de vistas que nos brindan metadatos sobre los objetos de nuestra base de datos. En este caso necesitamos user_tab_columns , que nos dará las columnas para una tabla dada. Lo segundo es SQL dinámico; esta es la capacidad de ensamblar una consulta SQL en tiempo de ejecución y luego ejecutarla. Hay un par de formas de hacer esto, pero normalmente los cursores de referencia son suficientes.

El siguiente código es una prueba de concepto. Toma cuatro parámetros:

  1. el nombre de la tabla que desea buscar
  2. el nombre de la columna clave principal de esa tabla
  3. el valor de clave principal por el que desea restringir
  4. el valor que desea buscar.

Está en bruto y listo, por lo que es posible que deba editarlo para ordenar la salida o para hacer que el programa sea más flexible.

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 puede ver, SQL dinámico es difícil de leer. Es más difícil de depurar :) Por lo tanto, es una buena idea tener un medio para mostrar la declaración final.

De todos modos, aquí están los 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>