sql >> Databáze >  >> RDS >> Oracle

sběr záznamů do sys_refcursor

Za předpokladu, že vaše formData struktura tabulky je pevná a známá, stačí použít výraz typu case k překladu formOption.fName na odpovídající hodnotu sloupce:

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                                   

Poté můžete nechat svou proceduru otevřít referenční kurzor pro tento dotaz pomocí hodnoty argumentu pro hodnotu ID.

Pokud formData struktura není známá nebo není statická, pak máte pravděpodobně větší problémy; ale k tomu byste se museli vrátit k dynamickému SQL. Jako výchozí bod můžete udělat něco jako:

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

To používá všechny sloupce skutečně definované v tabulce k vytvoření výrazu případu za běhu; protože velikost vašeho fieldName nemusí odpovídat datovému slovníku, pro srovnání nutím vše na malá písmena. Také se omezuji na řetězcové sloupce, aby se případ zjednodušil, ale pokud potřebujete sloupce, které jsou jinými datovými typy, pak každý when ... then klauzule případových výrazů by potřebovala zkontrolovat datový typ daného sloupce (který můžete přidat do r kurzor) a odpovídajícím způsobem převést skutečnou hodnotu sloupce na řetězec. Všechny hodnoty musí mít stejný datový typ, takže to musí být opravdu řetězce.

Každopádně, testování to z 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.

Můžete se zeptat na fieldOptions místo toho získat možné názvy sloupců, ale stále můžete mít problém s převodem datových typů, se kterým by bylo obtížnější se vypořádat; ale pokud všechny odkazované formData pole jsou ve skutečnosti řetězce, pak by to bylo:

  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;


  1. Postgres where klauzule porovnat časové razítko

  2. Jak funguje UNCOMPRESSED_LENGTH() v MariaDB

  3. Spring Data JPA + Hibernate Přeskočení zamčených řádků (PostgreSQL)

  4. komponenta skriptu chybí odkaz na Oracle