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

raccolta di record su sys_refcursor

Assumendo i tuoi formData la struttura della tabella è fissa e nota, puoi semplicemente usare un'espressione case per tradurre formOption.fName al valore della colonna corrispondente:

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                                   

È quindi possibile fare in modo che la procedura apra un cursore di riferimento per quella query, utilizzando un valore di argomento per il valore ID.

Se il formData la struttura non è nota o non è statica, quindi probabilmente hai problemi più grandi; ma per questo dovresti ricorrere all'SQL dinamico. Come punto di partenza, potresti fare qualcosa del tipo:

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

Questo utilizza tutte le colonne effettivamente definite nella tabella per creare l'espressione case in fase di esecuzione; perché è il caso del tuo fieldName potrebbe non corrispondere al dizionario dei dati, sto costringendo tutto a minuscolo per il confronto. Mi sto anche limitando alle colonne di stringa per semplificare il caso, ma se hai bisogno di colonne che siano altri tipi di dati, allora ogni when ... then La clausola delle espressioni case dovrebbe controllare il tipo di dati di quella colonna (che puoi aggiungere a r cursore) e convertire il valore effettivo della colonna in una stringa in modo appropriato. Tutti i valori devono avere lo stesso tipo di dati, quindi devono essere stringhe, in realtà.

Ad ogni modo, testandolo da 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.

Puoi interrogare fieldOptions per ottenere invece i possibili nomi delle colonne, ma potresti comunque avere il problema di conversione del tipo di dati, che sarebbe più difficile da affrontare; ma se tutti i formData di riferimento i campi sono in realtà stringhe, quindi sarebbe:

  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;