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

collection d'enregistrements vers sys_refcursor

En supposant que votre formData la structure de la table est fixe et connue, vous pouvez simplement utiliser une expression de cas pour traduire le formOption.fName à la valeur de colonne correspondante :

select fo.fieldLabel as label,
  case fo.fieldName
    when 'fName' then fd.fName
    when 'lName' then fd.lName
    when 'nName' then fd.mName
  end as value
from formData fd
join fieldOptions fo
on fo.formType = fd.formtype
where fd.id = 3;

LABEL                VALUE               
-------------------- --------------------
First                Frank               
Surname              Peterson            
Middle Initial                           

...
where fd.id = 3;

LABEL                VALUE               
-------------------- --------------------
First Name           Bob                 
Last Name            Smith               
Middle                                   

Vous pouvez ensuite faire en sorte que votre procédure ouvre un curseur de référence pour cette requête, en utilisant une valeur d'argument pour la valeur d'ID.

Si le formData la structure n'est pas connue ou n'est pas statique, alors vous avez probablement de plus gros problèmes ; mais pour cela, vous devrez revenir au SQL dynamique. Comme point de départ, vous pourriez faire quelque chose comme :

create procedure p42 (p_id number, p_refcursor out sys_refcursor) as
  l_stmt varchar2(32767);
begin
  l_stmt := 'select fo.fieldLabel as label, case lower(fo.fieldName) ';
  for r in (
    select column_name from user_tab_columns
    where table_name = 'FORMDATA'
    and data_type = 'VARCHAR2'
  )
  loop
    l_stmt := l_stmt || ' when ''' || lower(r.column_name) || ''' then fd.' || r.column_name;
  end loop;
  l_stmt := l_stmt || ' end as value '
    || 'from formData fd '
    || 'join fieldOptions fo '
    || 'on fo.formType = fd.formtype '
    || 'where fd.id = :d1';
  open p_refcursor for l_stmt using p_id;
end p42;
/

Cela utilise toutes les colonnes réellement définies dans la table pour créer l'expression case au moment de l'exécution; car la casse de votre fieldName peut ne pas correspondre au dictionnaire de données, je force tout en minuscules pour comparaison. Je me limite également aux colonnes de chaînes pour simplifier le cas, mais si vous avez besoin de colonnes qui sont d'autres types de données, alors chaque when ... then la clause des expressions de cas devrait vérifier le type de données de cette colonne (que vous pouvez ajouter au r curseur) et convertissez la valeur réelle de la colonne en chaîne de manière appropriée. Toutes les valeurs doivent finir par le même type de données, donc il doit s'agir de chaînes, vraiment.

Quoi qu'il en soit, testez ceci depuis SQL*Plus :

var rc refcursor
exec p42(1, :rc);

PL/SQL procedure successfully completed.

print rc

LABEL                VALUE
-------------------- --------------------
First Name           Bob
Last Name            Smith
Middle

3 rows selected.

Vous pouvez interroger fieldOptions pour obtenir les noms de colonne possibles à la place, mais vous pouvez toujours avoir le problème de conversion de type de données, ce qui serait plus difficile à gérer ; mais si tous les formData référencés les champs sont en fait des chaînes alors ce serait :

  for r in (
    select fo.fieldName
    from formData fd
    join fieldOptions fo
    on fo.formType = fd.formtype
    where fd.id = p_id
  )
  loop
    l_stmt := l_stmt || ' when ''' || r.fieldName || ''' then fd.' || r.fieldName;
  end loop;