sql >> Database >  >> RDS >> Oracle

verzameling van records naar out sys_refcursor

Uitgaande van uw formData tabelstructuur is vast en bekend, u kunt gewoon een case-expressie gebruiken om de formOption.fName te vertalen naar de overeenkomende kolomwaarde:

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                                   

U kunt uw procedure dan een ref-cursor voor die query laten openen, met een argumentwaarde voor de ID-waarde.

Als de formData structuur niet bekend is, of niet statisch is, dan heb je waarschijnlijk grotere problemen; maar hiervoor moet je terugvallen op dynamische SQL. Als uitgangspunt zou je zoiets kunnen doen:

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

Dit gebruikt alle kolommen die daadwerkelijk in de tabel zijn gedefinieerd om de case-expressie tijdens runtime te maken; omdat het geval van uw fieldName komt misschien niet overeen met de datadictionary, ik dwing alles in kleine letters ter vergelijking. Ik beperk me ook tot stringkolommen om de zaak eenvoudiger te maken, maar als je kolommen nodig hebt die andere gegevenstypen zijn, dan moet elke when ... then clausule van de case-expressies zou het gegevenstype van die kolom moeten controleren (die u kunt toevoegen aan de r cursor) en converteer de werkelijke kolomwaarde op de juiste manier naar een tekenreeks. Alle waarden moeten hetzelfde datatype hebben, dus het moeten eigenlijk strings zijn.

Hoe dan ook, dit testen vanuit 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.

U kunt fieldOptions . opvragen om in plaats daarvan de mogelijke kolomnamen te krijgen, maar u hebt mogelijk nog steeds het probleem met de conversie van het gegevenstype, wat moeilijker te behandelen is; maar als alle genoemde formData velden zijn eigenlijk strings, dan zou dat zijn:

  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. JSON-kolom schrijven naar Postgres met Pandas .to_sql

  2. Hoe het MySQL-rootaccountwachtwoord op CentOS7 wijzigen?

  3. Vrije plaatsen vinden in een boekingssysteem

  4. CREATE TABLE als SELECT - met behulp van MEMORY ENGINE (in RAM-geheugen)