Oracle
 sql >> Base de données >  >> RDS >> Oracle

SQL :rechercher une liste de colonnes avec une valeur donnée (dans une ligne)

Ce n'est pas une fonctionnalité normale de la base de données. Cependant, vous n'êtes pas la première personne à avoir demandé cela, ou quelque chose comme ça.

La solution nécessite deux choses. Le premier est le dictionnaire de données; la base de données Oracle ne prend pas en charge la réflexion, mais elle est livrée avec un ensemble de vues qui nous donnent des métadonnées sur nos objets de base de données. Dans ce cas, nous avons besoin de user_tab_columns , qui nous donnera les colonnes d'une table donnée. La deuxième chose est le SQL dynamique; c'est la possibilité d'assembler une requête SQL au moment de l'exécution, puis de l'exécuter. Il existe plusieurs manières de procéder, mais les curseurs de référence suffisent généralement.

Le code suivant est une preuve de concept. Il prend quatre paramètres :

  1. le nom de la table que vous souhaitez rechercher
  2. le nom de la colonne clé primaire de cette table
  3. la valeur de la clé primaire que vous souhaitez restreindre
  4. la valeur que vous souhaitez rechercher.

Il est prêt à l'emploi, vous devrez donc peut-être le modifier pour ranger la sortie ou pour rendre le programme plus 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;
/

Comme vous pouvez le constater, le SQL dynamique est difficile à lire. C'est plus difficile à déboguer :) C'est donc une bonne idée d'avoir un moyen d'afficher la déclaration finale.

Quoi qu'il en soit, voici les résultats :

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>