Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

coleção de registros para fora sys_refcursor


Supondo que seu formData a estrutura da tabela é fixa e conhecida, você pode usar apenas uma expressão case para traduzir o formOption.fName para o valor da coluna correspondente:
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                                   

Você pode então fazer com que seu procedimento abra um cursor de referência para essa consulta, usando um valor de argumento para o valor de ID.

Se o formData estrutura não é conhecida, ou não é estática, então você provavelmente terá problemas maiores; mas para isso você precisaria voltar ao SQL dinâmico. Como ponto de partida, você pode fazer algo como:
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;
/

Isso usa todas as colunas realmente definidas na tabela para criar a expressão case em tempo de execução; porque o caso do seu fieldName pode não corresponder ao dicionário de dados, estou forçando tudo para minúsculas para comparação. Também estou restringindo a colunas de string para simplificar o caso, mas se você precisar de colunas que são outros tipos de dados, cada when ... then cláusula das expressões case precisaria verificar o tipo de dados dessa coluna (que você pode adicionar ao r cursor) e converta o valor real da coluna em uma string apropriadamente. Todos os valores têm que terminar no mesmo tipo de dados, então tem que ser strings, na verdade.

De qualquer forma, testando isso do 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.

Você pode consultar fieldOptions para obter os possíveis nomes das colunas, mas você ainda pode ter o problema de conversão de tipo de dados, que seria mais difícil de lidar; mas se todos os formData referenciados campos são na verdade strings, então isso seria:
  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;