PL/SQL – используйте одну и ту же конвейерную функцию дважды в одном запросе

StackOverflow https://stackoverflow.com/questions/1903908

Вопрос

Я пытаюсь использовать конвейерную функцию, чтобы сэкономить время и уменьшить избыточность в моих запросах.Рассматриваемая функция возвращает данные из справочной таблицы на основе некоторых входных данных.Записи в основной таблице данных, из которой я выбираю, имеют несколько столбцов, все из которых относятся к справочной таблице.Проблема, с которой я сталкиваюсь, заключается в том, что когда я пытаюсь использовать конвейерную функцию более одного раза в запросе, я получаю ошибку «курсор уже открыт».

Например:

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;

Это работало нормально, пока я не добавил вторую ссылку в свою функцию конвейера (fn_getOvrdValXML), и теперь я получаю ошибку «курсор уже открыт».

Конвейерная функция очень проста:

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;

Курсор аналогичен простому:

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;

Есть ли способ обойти это, или мне следует попытаться решить эту проблему (проблему необходимости ссылаться на ovrd_val и выводить xmlforest одним и тем же способом много-много-много раз) по-другому?

Признаюсь, я новичок в конвейерных функциях, поэтому не уверен на 100%, что это подходящее использование, но в то время это имело смысл, и я открыт для других идей;)

Это было полезно?

Решение

Если вы используете конвейерные функции, то у вас минимум 9i, что означает, что вы можете использовать предложение 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;

Непроверено, и тоже непонятно, к чему вы присоединяетесь - отсюда и ? по критериям присоединения.

Другие советы

Пробовали ли вы закрыть курсор внутри этой конвейерной функции перед передачей строки?

OPEN C_OvrdVal(in_ID);
FETCH c_OrdVal INTO my_chunk_variable;
CLOSE C_OrdVal;
PIPE ROW my_chunk_variable;
RETURN;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top