如何从 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
*/
我有一个 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
*/