PL/SQL 将本地集合传递给流水线函数
PL/SQL Passing a local collection into a pipelined function
我需要将本地定义的 table 类型传递给函数,该函数是返回另一个本地定义的 table 类型的流水线函数。
这是示例数据:
create table my_tab
(i NUMBER,
n VARCHAR2(30));
insert into my_tab values (1, 'Peter');
insert into my_tab values (2, 'Dakshesh');
insert into my_tab values (1, 'Maggie');
insert into my_tab values (3, 'Madhu');
commit;
我的代码是:
CREATE OR REPLACE PACKAGE my_pkg IS
TYPE t_col IS RECORD(
i NUMBER,
n VARCHAR2(30));
TYPE t_nested_table IS TABLE OF t_col;
TYPE t_number IS TABLE OF NUMBER;
FUNCTION iterate_table RETURN t_number PIPELINED;
FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED;
g_number t_number ;
g_nested_number t_nested_table ;
END my_pkg;
/
正文:
CREATE OR REPLACE PACKAGE BODY my_pkg IS
FUNCTION iterate_table RETURN t_number PIPELINED IS
BEGIN
IF ( (g_number IS NOT NULL) AND (g_number.EXISTS (1)))
THEN
FOR i IN 1 .. g_number.COUNT
LOOP
IF g_number (i) IS NOT NULL
THEN
PIPE ROW (g_number (i));
END IF;
END LOOP;
END IF;
RETURN;
EXCEPTION
WHEN OTHERS
THEN
RAISE;
END iterate_table;
FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED IS
l_row t_nested_table ;
CURSOR cur_test IS
select mt.i, mt.n
from my_tab mt, TABLE(iterate_table ) tab
where mt.i = tab.column_value;
BEGIN
OPEN cur_test;
FETCH cur_test BULK COLLECT into l_row;
CLOSE cur_test;
FOR i IN 1..l_row.COUNT
LOOP
PIPE ROW(l_row(i));
END LOOP;
RETURN;
END return_table;
END my_pkg;
/
现在这段代码编译成功,当我尝试像管道函数一样调用它时,它给出了错误-
select * from table(my_pkg.return_table(my_pkg.t_number(1)));
错误-
ORA-00902: 无效的数据类型
00902.00000 - "invalid datatype"
*原因:<br>
*行动:
行错误:14 列:41
此代码的两个先决条件是 -
集合应该都是本地定义的。
函数应该流水线化。
求助!!
我没有收到 table 的任何错误,它是一个 table,所以没有外键约束。
在 oracle 11 中是不可能的。我不知道为什么 oracle 会抛出 "invalid data type"。
如果您将此查询放入匿名块中,您将收到 PLS-00642: Local Collection Types Not Allowed in SQL Statement
如果您不想或无法创建 sql 关卡 collection。解决方案是使用预定义类型。预定义 collection 的良好来源是 Oracle Data Cartridge
。将所有 t_number
替换为 ODCINumberList
。
在 Oracle 10 和 11 中,无法使用已在 PL/SQL 范围内定义的 SQL 范围内的集合。 In Oracle 12,您尝试的应该有效。
如果您想这样做,请在 SQL 范围内(而不是在包中)声明您的类型。
CREATE OR REPLACE TYPE t_col IS OBJECT(
i NUMBER,
n VARCHAR2(30)
);
/
CREATE OR REPLACE TYPE t_nested_table IS TABLE OF t_col;
/
CREATE OR REPLACE TYPE t_number IS TABLE OF NUMBER;
/
CREATE OR REPLACE PACKAGE my_pkg IS
FUNCTION iterate_table RETURN t_number PIPELINED;
FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED;
g_number t_number ;
g_nested_number t_nested_table ;
END my_pkg;
/
我需要将本地定义的 table 类型传递给函数,该函数是返回另一个本地定义的 table 类型的流水线函数。
这是示例数据:
create table my_tab
(i NUMBER,
n VARCHAR2(30));
insert into my_tab values (1, 'Peter');
insert into my_tab values (2, 'Dakshesh');
insert into my_tab values (1, 'Maggie');
insert into my_tab values (3, 'Madhu');
commit;
我的代码是:
CREATE OR REPLACE PACKAGE my_pkg IS
TYPE t_col IS RECORD(
i NUMBER,
n VARCHAR2(30));
TYPE t_nested_table IS TABLE OF t_col;
TYPE t_number IS TABLE OF NUMBER;
FUNCTION iterate_table RETURN t_number PIPELINED;
FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED;
g_number t_number ;
g_nested_number t_nested_table ;
END my_pkg;
/
正文:
CREATE OR REPLACE PACKAGE BODY my_pkg IS
FUNCTION iterate_table RETURN t_number PIPELINED IS
BEGIN
IF ( (g_number IS NOT NULL) AND (g_number.EXISTS (1)))
THEN
FOR i IN 1 .. g_number.COUNT
LOOP
IF g_number (i) IS NOT NULL
THEN
PIPE ROW (g_number (i));
END IF;
END LOOP;
END IF;
RETURN;
EXCEPTION
WHEN OTHERS
THEN
RAISE;
END iterate_table;
FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED IS
l_row t_nested_table ;
CURSOR cur_test IS
select mt.i, mt.n
from my_tab mt, TABLE(iterate_table ) tab
where mt.i = tab.column_value;
BEGIN
OPEN cur_test;
FETCH cur_test BULK COLLECT into l_row;
CLOSE cur_test;
FOR i IN 1..l_row.COUNT
LOOP
PIPE ROW(l_row(i));
END LOOP;
RETURN;
END return_table;
END my_pkg;
/
现在这段代码编译成功,当我尝试像管道函数一样调用它时,它给出了错误-
select * from table(my_pkg.return_table(my_pkg.t_number(1)));
错误-
ORA-00902: 无效的数据类型
00902.00000 - "invalid datatype"
*原因:<br>
*行动:
行错误:14 列:41
此代码的两个先决条件是 -
集合应该都是本地定义的。
函数应该流水线化。
求助!!
我没有收到 table 的任何错误,它是一个 table,所以没有外键约束。
在 oracle 11 中是不可能的。我不知道为什么 oracle 会抛出 "invalid data type"。
如果您将此查询放入匿名块中,您将收到 PLS-00642: Local Collection Types Not Allowed in SQL Statement
如果您不想或无法创建 sql 关卡 collection。解决方案是使用预定义类型。预定义 collection 的良好来源是 Oracle Data Cartridge
。将所有 t_number
替换为 ODCINumberList
。
在 Oracle 10 和 11 中,无法使用已在 PL/SQL 范围内定义的 SQL 范围内的集合。 In Oracle 12,您尝试的应该有效。
如果您想这样做,请在 SQL 范围内(而不是在包中)声明您的类型。
CREATE OR REPLACE TYPE t_col IS OBJECT(
i NUMBER,
n VARCHAR2(30)
);
/
CREATE OR REPLACE TYPE t_nested_table IS TABLE OF t_col;
/
CREATE OR REPLACE TYPE t_number IS TABLE OF NUMBER;
/
CREATE OR REPLACE PACKAGE my_pkg IS
FUNCTION iterate_table RETURN t_number PIPELINED;
FUNCTION return_table(in_t_num t_number) RETURN t_nested_table PIPELINED;
g_number t_number ;
g_nested_number t_nested_table ;
END my_pkg;
/