sql >> Base de Datos >  >> RDS >> Oracle

colección de registros a cabo sys_refcursor

Asumiendo su formData la estructura de la tabla es fija y conocida, solo puede usar una expresión de mayúsculas y minúsculas para traducir formOption.fName al valor de la columna coincidente:

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                                   

Luego puede hacer que su procedimiento abra un cursor de referencia para esa consulta, usando un valor de argumento para el valor de ID.

Si el formData la estructura no se conoce, o no es estática, entonces probablemente tenga problemas mayores; pero para esto necesitaría recurrir a SQL dinámico. Como punto de partida, podría hacer 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;
/

Esto usa todas las columnas realmente definidas en la tabla para crear la expresión de caso en tiempo de ejecución; porque el caso de su fieldName puede que no coincida con el diccionario de datos, estoy forzando todo a minúsculas para comparar. También estoy restringiendo las columnas de cadena para simplificar el caso, pero si necesita columnas que son otros tipos de datos, entonces cada when ... then cláusula de las expresiones de caso necesitaría verificar el tipo de datos de esa columna (que puede agregar al r cursor) y convierta el valor real de la columna en una cadena de forma adecuada. Todos los valores deben terminar en el mismo tipo de datos, por lo que en realidad deben ser cadenas.

De todos modos, probando esto desde 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.

Puede consultar fieldOptions para obtener los posibles nombres de columna en su lugar, pero aún puede tener el problema de conversión de tipo de datos, que sería más difícil de manejar; pero si todos los formData referenciados los campos son en realidad cadenas, entonces eso sería:

  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;