流水线函数调用另一个流水线函数

发布于 2024-08-31 16:21:30 字数 1629 浏览 4 评论 0原文

这是一个包含两个管道函数的包:

create or replace type tq84_line as table of varchar2(25);
/

create or replace package tq84_pipelined as

    function more_rows return tq84_line pipelined;
    function go        return tq84_line pipelined;

end tq84_pipelined;
/

Ant 相应的包主体:

create or replace package body tq84_pipelined as

    function more_rows return tq84_line pipelined is
    begin

        pipe row('ist');
        pipe row('Eugen,');

        return;

    end more_rows;

    function go return tq84_line pipelined is
    begin

        pipe row('Mein');
        pipe row('Name');

        /* start */
        for next in (
          select column_value line from table(more_rows)
        ) 
        loop
          pipe row(next.line);
        end loop;
        /* end */

        pipe row('ich');
        pipe row('weiss');
        pipe row('von');
        pipe row('nichts.');

    end go;

end tq84_pipelined;
/

重要的是 go 某种程度 使用 for next in ...< 调用 more_rows /code> /* start *//* end */

我可以按如下方式使用该包:

select * from table(tq84_pipelined.go);

这一切都很好,但我希望我可以替换通过简单调用 more_rows 即可显示 /* start *//* end */ 之间的行。

然而,这显然是不可能的,因为它生成了PLS-00221:'MORE_ROWS'不是一个过程或未定义

所以,我的问题是:真的没有办法缩短循环吗?

编辑

显然,从到目前为止的答案来看,我的问题尚不清楚。

如上所述,该软件包有效。

但我对标记 /* start *//* end */ 之间的 6 行(即:六行)感到困扰。我想用一行替换它们。但我还没有找到任何方法做到这一点。

Here's a package with two pipelined functions:

create or replace type tq84_line as table of varchar2(25);
/

create or replace package tq84_pipelined as

    function more_rows return tq84_line pipelined;
    function go        return tq84_line pipelined;

end tq84_pipelined;
/

Ant the corresponding package body:

create or replace package body tq84_pipelined as

    function more_rows return tq84_line pipelined is
    begin

        pipe row('ist');
        pipe row('Eugen,');

        return;

    end more_rows;

    function go return tq84_line pipelined is
    begin

        pipe row('Mein');
        pipe row('Name');

        /* start */
        for next in (
          select column_value line from table(more_rows)
        ) 
        loop
          pipe row(next.line);
        end loop;
        /* end */

        pipe row('ich');
        pipe row('weiss');
        pipe row('von');
        pipe row('nichts.');

    end go;

end tq84_pipelined;
/

The important thing is that go sort of calls more_rows with the for next in ... between /* start */ and /* end */

I can use the package as follows:

select * from table(tq84_pipelined.go);

This is all fine and dandy, but I hoped I could replace the lines between /* start */ and /* end */ with a simple call of more_rows.

However, this is obviously not possible, as it generetes a PLS-00221: 'MORE_ROWS' is not a procedure or is undefined.

So, my question: is there really no way to shortcut the loop?

EDIT

Obviously, from the answers so far, my question was not clear.

The package, as stated works.

But I am bothered with the 6 (that is: SIX) lines between the markers /* start */ and /* end */. I'd like to replace these with one single line. But I havent found any way doing that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浪推晚风 2024-09-07 16:21:30

管道函数的要点是提供 TABLE() 函数。我认为没有任何办法可以避免它。不幸的是,我们必须将其输出分配给 PL/SQL 变量。我们无法将管道函数分配给像这样的 nt := more_rows; 嵌套表,因为

PLS-00653: aggregate/table functions are not allowed in PL/SQL scope

它必须是 SELECT ... FROM TABLE()

我有一个稍微不同的解决方案供您考虑。不知道是否能解决你的根本问题。

create or replace package body tq84_pipelined as 

    function more_rows return tq84_line pipelined is 
    begin 

        pipe row('ist'); 
        pipe row('Eugen,'); 

        return; 

    end more_rows; 

    function go return tq84_line pipelined is 
        nt1 tq84_line;
        nt2 tq84_line;
        nt3 tq84_line;
        nt0 tq84_line;
    begin 

        nt1 := tq84_line('Mein','Name'); 

        select * 
        bulk collect into nt2
        from table(more_rows);

        nt3 := tq84_line('ich','weiss','von','nichts.'); 

        nt0 := nt1 multiset union nt2 multiset union nt3; 

        for i in nt0.first..nt0.last
        loop 
          pipe row(nt0(i)); 
        end loop; 

        return;

    end go; 

end tq84_pipelined; 
/

我确信您已经知道(但为了其他搜索者的利益),Oracle 10g 中引入了用于将集合组合在一起的 MULTISET UNION 语法。

此版本的 GO() 产生与原始实现相同的输出:

SQL> select * from table( tq84_pipelined.go)
  2  /

COLUMN_VALUE
-------------------------
Mein
Name
ist
Eugen,
ich
weiss
von
nichts.

8 rows selected.

SQL>

The point of pipelined functions is to feed TABLE() functions. I don't think there is any way to avoid it. Unfortunately we have to assign its output to a PL/SQL variable. We can't assign a pipelined function to a nested table like this nt := more_rows; due to

PLS-00653: aggregate/table functions are not allowed in PL/SQL scope

So SELECT ... FROM TABLE() it has to be.

I have a slightly different solution for your consideration. I don't know whether it solves your underlying problem.

create or replace package body tq84_pipelined as 

    function more_rows return tq84_line pipelined is 
    begin 

        pipe row('ist'); 
        pipe row('Eugen,'); 

        return; 

    end more_rows; 

    function go return tq84_line pipelined is 
        nt1 tq84_line;
        nt2 tq84_line;
        nt3 tq84_line;
        nt0 tq84_line;
    begin 

        nt1 := tq84_line('Mein','Name'); 

        select * 
        bulk collect into nt2
        from table(more_rows);

        nt3 := tq84_line('ich','weiss','von','nichts.'); 

        nt0 := nt1 multiset union nt2 multiset union nt3; 

        for i in nt0.first..nt0.last
        loop 
          pipe row(nt0(i)); 
        end loop; 

        return;

    end go; 

end tq84_pipelined; 
/

As I'm sure you're aware (but for the benefit of other seekers) the MULTISET UNION syntax for glomming collections together was introduced in Oracle 10g.

This version of GO() produces the same output as your original implementation:

SQL> select * from table( tq84_pipelined.go)
  2  /

COLUMN_VALUE
-------------------------
Mein
Name
ist
Eugen,
ich
weiss
von
nichts.

8 rows selected.

SQL>
逆夏时光 2024-09-07 16:21:30

尝试
从表中选择column_value行(tq84_line.more_rows)
即在查询中包含包名称。

Try
select column_value line from table(tq84_line.more_rows)
i.e. include the package name in the query.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文