如何从 Oracle 中的函数输出数组数据 PL/SQL

How to output array data from a function in Oralce PL/SQL

我有一个 PL/SQL 程序包,其中包含我需要用来验证结果的程序。

一个这样的例子:

create or replace PACKAGE    MY_TEST
IS
   PROCEDURE validate_my_value (p_input_value      INT,
                                p_valid        OUT INT);
END;

create or replace PACKAGE BODY    MY_TEST
IS
   PROCEDURE validate_my_value (p_input_value       INT,
                                p_valid         OUT INT)
   IS
   BEGIN
       p_valid := 0;
       IF MOD(p_input_value, 2) = 0 THEN
          p_valid := 1;
       END IF;
  END;  
END;

我想多次调用此过程,并且 return 来自另一个 PL/SQL 程序包上的函数的 sys_refcursor 中的有效结果。

我有一个例子,我在一个数组中收集有效结果,但最后我似乎无法完全正确地获得输出格式。

示例:

create or replace PACKAGE    MY_TEST_CLIENT
    IS
       FUNCTION get_validated_values (p_input_begin  INT,
                                      p_input_end    INT)
                                    RETURN sys_refcursor;
    
    END;
    
    
create or replace PACKAGE BODY    MY_TEST_CLIENT
IS
    TYPE t_num_array IS TABLE OF INTEGER;

    FUNCTION get_validated_values (p_input_begin  INT,
                                   p_input_end    INT)
                                   RETURN sys_refcursor
    IS
        l_current_value  INT;
        l_valid          INT;
        l_result_cursor  sys_refcursor;
        l_result         t_num_array := new t_num_array();
        l_count          INT := 1;
    BEGIN
        l_valid := 0;
        l_current_value := p_input_begin;

        LOOP
            MY_TEST.VALIDATE_MY_VALUE(l_current_value, l_valid);
            IF l_valid = 1 THEN
                l_result.extend();
                l_result(l_result.count) := l_current_value;
            END IF;
            EXIT WHEN l_current_value >= p_input_end;
            l_current_value := l_current_value + 1;
        END LOOP;

        IF l_result.count() = 0 THEN
            return l_result_cursor;
        END IF;

       -- TODO convert l_result into l_result_cursor
       open l_result_cursor for
        -- SELECT * FROM TABLE(l_result); -- This does not work. ORA-22905 and ORA-00642
        select 1 from dual; -- Dummy value
        return l_result_cursor;
    END;
END;

最后我希望能够像这样调用方法:

SELECT MY_TEST_CLIENT.get_validated_values(1,10) from DUAL;

因此,根据此处的示例,验证器应该只产生相同的数字。例如:2、4、6、8 和 10。

我尝试了类似于 的操作,但无法让输出游标接受结果。

我还尝试遍历结果并创建一个 SQL 语句(select 来自对偶联合的值 ...)。但是,我没有运气执行生成的 SQL 语句,结果是 sys_refcursor.

可以 return 编辑的结果

任何关于如何输出结果的指示将不胜感激。

要使用 SELECT * FROM TABLE(l_result),您必须将类型创建为数据库对象,即

CREATE TYPE t_num_array IS TABLE OF INTEGER; 

而不是在 PL/SQL 包中定义它。

注意,你可以用这个“一行”得到相同的结果:

open l_result_cursor for
with t as
   (select rownum + p_input_begin as r
   from dual
   connect by rownum <= p_input_end+1)
select r
from t
where mod(r,2)= 0;

@Wernfried 给出了为什么我的初始问题有问题的线索,并且向数据库添加类型有助于使 SELET * FROM TABLE(l_result); 工作。

create or replace TYPE t_num_array AS TABLE OF INTEGER;

然而,@Justin 的管道建议在这种情况下实际上更有意义。因此,对于流水线输出,解决方案如下所示:

create or replace PACKAGE BODY    MY_TEST_CLIENT2
IS
    FUNCTION get_validated_values (p_input_begin  INT,
                                   p_input_end    INT)
                                    return t_num_array pipelined 
    IS
        l_current_value  INT;
        l_valid          INT;
    BEGIN
        l_valid := 0;
        l_current_value := p_input_begin;

        LOOP
            MY_TEST.VALIDATE_MY_VALUE(l_current_value, l_valid);
            IF l_valid = 1 THEN
                pipe row (l_current_value);
            END IF;
            EXIT WHEN l_current_value >= p_input_end;
            l_current_value := l_current_value + 1;
        END LOOP;
        RETURN;
    END;
END;

调用它会这样做:

SELECT MY_TEST_CLIENT2.get_validated_values(1,10) from DUAL;
-- TT.T_INTEGER_ARRAY(2, 4, 6, 8, 10)

或者使用@Justing

的建议
SELECT * from table(MY_TEST_CLIENT2.get_validated_values(1,10));
/*
2
4
6
8
10
*/