oracle - 如何有条件地连接 Oracle SQL 中的表函数(该函数以主表行列作为参数),而无需过多的函数调用?

标签 oracle plsql oracle11g

我有以下问题: 我的基表中的每一行都有一个标志列(下面列表中的“flg”)和一个函数参数列(“arg”)。如果在#N 行中标志为“Y”,则必须调用函数;之后,它将返回,比方说,一列(实际上是一堆,但我会尽可能简化)。最后,行 #N 应该转换为子表 - 行 #N 和函数返回的列的完全联接。 如果标志为“N”,则行 #N 的结果应为该行本身加上“函数返回列”中的 NULL。

这是一个例子:

create or replace package SIEBEL.TEST_PACKAGE as
    type ret_type is table of number;
    function testFunc(inp number)
    return ret_type
    pipelined;
end TEST_PACKAGE;
/
create or replace package body SIEBEL.TEST_PACKAGE is
    function testFunc(inp number)
    return ret_type
    pipelined
    is
    i number;
    begin
        dbms_output.put_line('Function call, arg = ' || to_char(inp));
        if (inp is null OR inp = 0) then
            pipe row (null);
        else
            for i in 1..inp loop
                 pipe row (i);
            end loop;
        end if;
    end testFunc;
end TEST_PACKAGE;
/
with base_table as
(
    select 'Shall invoke' col0, 'Y' flg, '2' arg from dual
    union
    select 'Shall not invoke' col0, 'N' flg, '0' arg from dual
)
select * from base_table t0, table(siebel.test_package.testFunc(t0.arg)) t1;

它将返回我真正想要的:

COL0              | FLG | ARG | COLUMN_VALUE
--------------------------------------------
Shall invoke      |  Y  |  2  |      1
Shall invoke      |  Y  |  2  |      2
Shall not invoke  |  N  |  0  |

问题是,即使对于“N”标志,该函数仍然被调用 - 数据库输出将显示

Function call, arg = 2
Function call, arg = 0

如果在现实世界中,我有数百 strip 有“Y”标志的记录,大约 100K strip 有“N”标志的记录。另外,我的实际函数要复杂得多,并且其 namespace 中有很多内容,因此每个函数调用对于性能而言都至关重要。

我真正想要的是示例的数据库输出:

Function call, arg = 2

我可以通过

实现它
with base_table as
    (
        select 'Shall invoke' col0, 'Y' flg, '2' arg from dual
        union
        select 'Shall not invoke' col0, 'N' flg, '0' arg from dual
    )
select t.*, t1.column_value
    from base_table t, table(SIEBEL.TEST_PACKAGE.testFunc(t.arg)) t1
    where t.flg = 'Y'
union all
select t.*, null as column_value
    from base_table t 
    where t.flg = 'N';

但随后所有索引都变得毫无用处 - 每个“order by”指令都需要很长时间才能完成。

请帮助我实现函数调用所需的行为,并仍然保存原始行顺序。

如果有什么不清楚的地方,请随时问我。

最诚挚的问候, 阿列克谢

最佳答案

对于 flag = "N",如果您有条件加入,则不会调用该函数

set serveroutput on
with base_table as
(
    select 'Shall invoke' col0, 'Y' flg, '2' arg from dual
    union
    select 'Shall not invoke' col0, 'N' flg, '0' arg from dual
)
select * from base_table t0
left join table( test_package.testFunc(t0.arg) ) t1 on (t0.flg = 'Y');

脚本输出

Package created.
Package body created.

COL0             FLG ARG COLUMN_VALUE
---------------- --- --- ------------
Shall invoke     Y   2              1
Shall invoke     Y   2              2
Shall not invoke N   0               

3 rows selected.

服务器输出:

Function call, arg = 2

关于oracle - 如何有条件地连接 Oracle SQL 中的表函数(该函数以主表行列作为参数),而无需过多的函数调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29411396/

相关文章:

sql - 如何在 PL/SQL 中查找字符串中不同字符的数量和名称

oracle - 在没有游标的情况下重构代码 PL/SQL

asp.net - 如何在只有 Oracle 12c 的机器上托管使用 Oracle 11g 的 ASP.NET 应用程序?

java - JDBC 在应用程序级别自动提交为 false

oracle - 合并具有不同列的两个表

python - python中与cx_Oracle绑定(bind)变量的异常

oracle - 无法通过 GET_FILE_NAME Oracle Forms 打开对话框

linux - 更改系统日期值?

Oracle:限制 "Other Users"可见

database - 使用来自 dbms_metadata.get_ddl 的 TIMESTAMP 表达式创建基于函数的索引后出现 ORA-01882