Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Sammlung von Datensätzen zu out sys_refcursor

Angenommen Ihre formData Tabellenstruktur festgelegt und bekannt ist, können Sie einfach einen Fallausdruck verwenden, um die formOption.fName zu übersetzen zum passenden Spaltenwert:

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                                   

Sie können Ihre Prozedur dann einen Ref-Cursor für diese Abfrage öffnen lassen, indem Sie einen Argumentwert für den ID-Wert verwenden.

Wenn die formData Struktur ist nicht bekannt oder nicht statisch, dann haben Sie wahrscheinlich größere Probleme; aber dafür müssten Sie auf dynamisches SQL zurückgreifen. Als Ausgangspunkt könnten Sie Folgendes tun:

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

Dies verwendet alle Spalten, die tatsächlich in der Tabelle definiert sind, um den case-Ausdruck zur Laufzeit zu erstellen; weil der Fall Ihres fieldName stimmt möglicherweise nicht mit dem Datenwörterbuch überein, ich erzwinge zum Vergleich alles in Kleinbuchstaben. Ich beschränke mich auch auf Zeichenfolgenspalten, um den Fall zu vereinfachen, aber wenn Sie Spalten benötigen, die andere Datentypen sind, dann jeweils when ... then -Klausel der case-Ausdrücke müsste den Datentyp dieser Spalte überprüfen (den Sie dem r hinzufügen können Cursor) und konvertieren Sie den tatsächlichen Spaltenwert entsprechend in eine Zeichenfolge. Alle Werte müssen denselben Datentyp haben, also müssen es wirklich Strings sein.

Wie auch immer, testen Sie dies von 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.

Sie könnten fieldOptions abfragen um stattdessen die möglichen Spaltennamen zu erhalten, aber Sie haben möglicherweise immer noch das Problem der Datentypkonvertierung, das schwieriger zu handhaben wäre; aber wenn alle referenzierten formData Felder sind eigentlich Strings, dann wäre das:

  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;