包含使用 with 子句的 sql 的 oracle 管道函数

Posted

技术标签:

【中文标题】包含使用 with 子句的 sql 的 oracle 管道函数【英文标题】:oracle pipeline function containing sql using with clause 【发布时间】:2017-07-27 17:16:51 【问题描述】:

我正在尝试创建一个函数,该函数返回一个对象,该对象可用作 select 语句中的表。根据对 oracle 文档的研究,我发现我需要一个 PIPELINED 函数。使用 sql 的管道函数的语法有问题。提前致谢!

DROP TYPE ODSMaxVRSN_ROW;
DROP TYPE ODSMaxVRSN_TBL;

CREATE OR REPLACE TYPE ODSMaxVRSN_ROW 
AS OBJECT
(
  sls_tran_key                          INT,
  sls_tran_key_unaud      int,
  audit_sls_trans_key     int,
  sls_4_part_key                     varchar2(50),
  sls_audit_rvsn_nbr      VARCHAR2(25)
)
/

CREATE OR REPLACE TYPE ODSMaxVRSN_TBL AS TABLE OF ODSMaxVRSN_ROW
/

  -- Declare the function
function GET_ODSMaxVRSN(in_dtFmt varchar2,
                        in_start_date varchar2,
                        in_end_date varchar2)
         return ODSMaxVRSN_TBL pipelined  is 

rt ODSMaxVRSN_TBL;
l_sql    VARCHAR2(2000);
l_cursor  SYS_REFCURSOR; 

begin
    -- Your query to load the table type 

                l_sql := 'With sales as (
                select s.SLS_TRANS_KEY,s.SLS_4_PART_KEY, nvl(s.SLS_AUDIT_RVSN_NBR,0), a.AUDIT_SLS_TRANS_KEY 
                from SLS_TRANS s
                left outer join AUDIT_SLS_TRANS a 
                                                on s.SLS_4_PART_KEY = a.SLS_4_PART_KEY and a.SLS_AUDIT_RVSN_NBR = 1
                where s.REC_CRT_TS between to_date(''' || in_start_date ||',''' || in_dtFmt || ') and to_date(''' || in_end_date ||',''' || in_dtFmt || ')''
                                and  a.AUDIT_SLS_TRANS_KEY > 0
                                                OR s.SLS_AUDIT_RVSN_NBR  > 0
                )              , maxrvsn as (
                Select trn.SLS_4_PART_KEY , max(n) SLS_AUDIT_RVSN_NBR
                                from sales trn 
                                group by trn.sls_4_part_key
                )              , unaudited as (
                select  t.SLS_TRANS_KEY, t.SLS_4_PART_KEY, t.SLS_AUDIT_RVSN_NBR
                from SLS_TRANS  t
                where t.SLS_AUDIT_RVSN_NBR is null
                )
                select t.AUDIT_SLS_TRANS_KEY, t.SLS_TRANS_KEY, t.SLS_4_PART_KEY, t.SLS_AUDIT_RVSN_NBR, u.sls_trans_key unaud_sls_trans_key
                from sales t
                inner join maxrvsn m on m.SLS_4_PART_KEY = t.SLS_4_PART_KEY and m.SLS_AUDIT_RVSN_NBR = t.SLS_AUDIT_RVSN_NBR
                INNER join unaudited u on t.SLS_4_PART_KEY = u.SLS_4_PART_KEY';

  OPEN l_cursor FOR l_sql;
  FETCH l_cursor BULK COLLECT INTO rt;
  CLOSE l_cursor;

    -- Stuff the results into the pipeline..
  if rt.count > 0 then 
    for i in rt.FIRST .. rt.LAST loop 
      pipe row (rt(i)); 
    end loop; 
  end if;

    -- Add more results as you please....
return;

end GET_ODSMaxVRSN;
/

【问题讨论】:

【参考方案1】:

您可以尝试在循环中一次获取和管道一行,而不是执行BULK COLLECT 然后循环遍历表。例如,请参见此处:http://www.oracle-developer.net/display.php?id=429

function GET_ODSMaxVRSN(in_dtFmt varchar2,
                        in_start_date varchar2,
                        in_end_date varchar2)
         return ODSMaxVRSN_TBL pipelined  is 

l_row ODSMaxVRSN_ROW;
l_sql    VARCHAR2(2000);
l_cursor  SYS_REFCURSOR; 

begin

    l_sql := '--your query--';

    OPEN l_cursor FOR l_sql;
    loop
        fetch l_cursor into l_row;
        exit when l_cursor%NOTFOUND;

        pipe row (l_row);

    end loop;
    CLOSE l_cursor;
    return;
end GET_ODSMaxVRSN;
/

【讨论】:

感谢您的建议。 当我尝试使用未定义的 l_sql 和 l_cursor 进行编译时,我仍然收到错误消息。还有什么需要补充的吗?

以上是关于包含使用 with 子句的 sql 的 oracle 管道函数的主要内容,如果未能解决你的问题,请参考以下文章

WITH子句中的PL/SQL

Oracle Reports 中的从属 WITH 子句

在 Oracle 中使用 connect by 在 with 子句中访问子查询中的父别名

如何在标准 SQL 的 WHERE 子句中使用 WITH 子查询作为选项列表

Oracle 使用 with 子句创建表

ORACLE 11G 中的 WITH 子句使用 UNION ALL