ORA-06504: PL/SQL: 执行时返回结果集变量的类型
Posted
技术标签:
【中文标题】ORA-06504: PL/SQL: 执行时返回结果集变量的类型【英文标题】:ORA-06504: PL/SQL: Return types of Result Set variables while execution 【发布时间】:2017-08-21 13:45:35 【问题描述】:我创建了一个如下的对象和过程,执行时出现以下错误。
ORA-06504:PL/SQL:返回结果集变量或查询的类型 不匹配 ORA-06512:在第 8 行
CREATE OR REPLACE TYPE OBJ_TST AS OBJECT
(
COl_ID NUMBER (30, 0),
Col_DATE TIMESTAMP (6)
);
/
create or replace TYPE OBJ_TBL AS TABLE OF OBJ_TST;
/
CREATE OR REPLACE PROCEDURE TST_OBJ (input_date IN DATE,
out_cur OUT SYS_REFCURSOR )
AS
l_tab OBJ_TBL := OBJ_TBL ();
BEGIN
SELECT OBJ_TST (ti.col_id, ti.col_date)
BULK COLLECT INTO l_tab
FROM MY_TBL ti
WHERE ti.create_date BETWEEN input_date AND input_date + 1;
Open o_cur for select col_id,col_date from table(l_tab);
END TST_OBJ;
/
执行给我带来了上述错误。 MY_TBL 的列数据类型(col_id 和 col_date)与我的对象相同。
DECLARE
a SYS_REFCURSOR;
var1 OBJ_TBL;
BEGIN
TST_OBJ (input_date => '21-Aug-2017', out_cur => a);
FETCH a bulk collect INTO var1;
For rec in 1..var1.count
LOOP
DBMS_OUTPUT.put_line (var1(rec).col_id ||' '|| var1(rec).Col_DATE);
END LOOP;
END;
/
ORA-06504:PL/SQL:返回结果集变量或查询的类型 不匹配 ORA-06512:在第 8 行
但是,当我这样执行时,它工作正常:
DECLARE
a SYS_REFCURSOR;
var1 NUMBER;
var2 TIMESTAMP (6);
BEGIN
TST_OBJ (i_date => '21-Aug-2017', out_cur => a);
LOOP
FETCH a INTO var1, var2;
EXIT WHEN a%NOTFOUND;
DBMS_OUTPUT.put_line (var1 ||' '|| var2);
END LOOP;
END;
谁能建议这里有什么问题?
【问题讨论】:
【参考方案1】:您正在使用表集合表达式来取消嵌套表集合:
Open out_cur for select col_id,col_date from table(l_tab);
查询返回两个关系列,而不是单个对象,因此您的光标也有两列。尝试将两个关系列批量收集到匿名块中的单个对象中会引发异常。
我想你可以将它们重新组合为对象:
Open out_cur for select OBJ_TST(col_id,col_date) from table(l_tab);
或者如果您不想明确列出列/字段名称:
Open out_cur for select cast(multiset(select * from table(l_tab)) as obj_tbl) from dual;
但是在您的示例中,表类型有点毫无意义,您可以这样做:
CREATE OR REPLACE PROCEDURE TST_OBJ (input_date IN DATE,
out_cur OUT SYS_REFCURSOR )
AS
BEGIN
Open out_cur for
SELECT OBJ_TST (ti.col_id, ti.col_date)
FROM MY_TBL ti
WHERE ti.create_date BETWEEN input_date AND input_date + 1;
END TST_OBJ;
/
但我认为您对函数内部的集合还有其他用途 - 在查询和返回之前对其进行修改。或者,您可以使用 OBJ_TBL
类型的第二个参数而不是 ref 游标,因此调用者不必将其批量收集到自己的本地集合中。
【讨论】:
【参考方案2】:DECLARE
a SYS_REFCURSOR;
var1 OBJ_TBL;
BEGIN
TST_OBJ (input_date => '21-Aug-2017', out_cur => a);
FETCH a bulk collect INTO var1;
For rec in 1..var1.count
LOOP
DBMS_OUTPUT.put_line (var1(rec).col_id ||' '|| var1(rec).Col_DATE);
END LOOP;
END;
/
游标a
有两列,您正试图将它们批量收集到一个变量中。 Oracle 不会将它们包装在 OBJ_TST
对象中,并且无法匹配它们。
为什么要使用游标:
CREATE OR REPLACE PROCEDURE TST_OBJ (
input_date IN DATE,
out_objs OUT OBJ_TBL
)
AS
BEGIN
SELECT OBJ_TST( col_id, col_date)
BULK COLLECT INTO out_objs
FROM MY_TBL
WHERE create_date BETWEEN input_date AND input_date + 1;
END TST_OBJ;
/
那么你可以这样做:
DECLARE
var1 OBJ_TBL;
BEGIN
TST_OBJ (
input_date => DATE '2017-08-21',
out_objs => var1
);
For rec in 1..var1.count LOOP
DBMS_OUTPUT.put_line (var1(rec).col_id ||' '|| var1(rec).Col_DATE);
END LOOP;
END;
/
【讨论】:
@MTO 我希望使用sys_refcursor
作为OUT
参数。我知道实现我的要求的其他方法,但我一直在寻找我做了什么以及为什么它不起作用。另外,如果您看到我已经发布了显示 `sys_ref 内容的另一种方式,无论如何感谢您的回答。以上是关于ORA-06504: PL/SQL: 执行时返回结果集变量的类型的主要内容,如果未能解决你的问题,请参考以下文章