PL / SQL - utilizzare stessa funzione pipeline per due volte nella stessa query
-
19-09-2019 - |
Domanda
Sto cercando di utilizzare una funzione pipeline per risparmiare tempo e ridurre la ridondanza nelle mie domande. La funzione in questione restituisce i dati da una tabella di riferimento sulla base di alcuni input. Record nella tabella dati principale che sto scegliendo da avere più colonne che tutto fare riferimento alla tabella di riferimento. Il problema che ho incontrato è che quando cerco di usare la funzione di pipeline più di una volta nella query, ottengo un "cursore già aperto" errore.
Ad esempio:
select xmlelement("genInf", xmlelement("ID", vt.ID),
xmlelement("vID", vt.V_ID),
xmlelement("vNum", vt.V_NUM),
xmlelement("terrDataCode", TERR_CODE.column_value), --data is based on reference table
xmlelement("ABValCode", AB_VAL_CD.column_value), --data is based on reference table
...
from V_TAB vt, table(UTIL.fn_getOvrdValXML(vt.terr_cd_id)) TERR_CODE,
table(UTIL.fn_getOvrdValXML(vt.ab_val_id)) AB_VAL_CD
where vt.ID = in_vID;
Questo ha funzionato bene fino a quando ho aggiunto il secondo riferimento alla mia funzione di pipeline (fn_getOvrdValXML), e ora ottenere il "cursore già aperto" errore.
La funzione di pipeline è molto semplice:
type t_XMLTab is table of XMLType; --this type is in the spec
....
function fn_getOvrdValXML(in_ID in ovrd.id%type) return t_XMLTab
pipelined is
begin
for r in C_OvrdVal(in_ID) loop
pipe row(r.XMLChunk);
end loop;
return;
end;
Il cursore è altrettanto semplice:
cursor C_OvrdVal(in_ID in ovrd.id%type) is
select xmlforest(ID as "valueID", S_VAL as "sValue", U_VAL as "uplValue",
O_VAL as "oValue", O_IND as "oIndicator", F_VAL as "finalValue",
O_RSN as "reason") AS XMLChunk
from ovrd_val xov;
where xov.id = in_ID;
C'è un modo per ovviare a questo, o devo cercare di affrontare questo problema (il problema di dover fare riferimento ovrd_val ed emettere un xmlforest allo stesso modo molte molte molte molte volte) in modo diverso?
Lo ammetto Sono nuovo di funzioni pipeline così io non sono sicuro al 100% si tratta di un uso appropriato, ma aveva senso al momento e sono aperto ad altre idee;)
Soluzione
Se stai usando le funzioni di pipeline, allora siete sulla 9i minimo che significa che è possibile utilizzare la clausola WITH:
WITH ovrdValXML AS (
select xov.id,
xmlforest(ID as "valueID", S_VAL as "sValue", U_VAL as "uplValue",
O_VAL as "oValue", O_IND as "oIndicator", F_VAL as "finalValue",
O_RSN as "reason") AS XMLChunk
from ovrd_val xov)
SELECT xmlelement("genInf", xmlelement("ID", vt.ID),
xmlelement("vID", vt.V_ID),
xmlelement("vNum", vt.V_NUM),
xmlelement("terrDataCode", TERR_CODE.column_value), --data is based on reference table
xmlelement("ABValCode", AB_VAL_CD.column_value), --data is based on reference table
...
FROM V_TAB vt
JOIN ovrdValXML terr_code ON terr_code = vt.?
AND terr_code.id = vt.terr_cd_id
JOIN ovrdValXML ab_val_cd ON ab_val_cd = vt.?
AND ab_val_cd.id = vt.ab_val_cd
WHERE vt.id = IN_VID;
Non testato, e non è chiaro quello che sta unendo anche -. Da qui il ?
sui criteri di join
Altri suggerimenti
Hai provato realmente chiudere il cursore all'interno quella funzione pipeline alla connessione di fila?
OPEN C_OvrdVal(in_ID);
FETCH c_OrdVal INTO my_chunk_variable;
CLOSE C_OrdVal;
PIPE ROW my_chunk_variable;
RETURN;