Sql 使用ORA-32042递归获取SYS_REFCURSOR
我有一个定义如下的表:Sql 使用ORA-32042递归获取SYS_REFCURSOR,sql,oracle,plsql,cursor,Sql,Oracle,Plsql,Cursor,我有一个定义如下的表: create table my_tab as select '1' p, '2' c from dual union select '1' p, '3' c from dual union select '4' p, '5' c from dual union select '4' p, '6' c from dual union select '4' p, '2' c from dual union select '7' p,
create table my_tab as
select '1' p, '2' c from dual
union
select '1' p, '3' c from dual
union
select '4' p, '5' c from dual
union
select '4' p, '6' c from dual
union
select '4' p, '2' c from dual
union
select '7' p, '3' c from dual
union
select '8' p, '4' c from dual;
我有两种类型(HTHIS仅供参考。我尽可能简化了示例!):
从SYS_REFCURSOR打印内容的包(例如,返回一些伪数据):
我试过这个:
declare
v_cnt number(8);
my_cursor SYS_REFCURSOR;
begin
open my_cursor for with t1(p,
c) as
(select distinct null p, t.p as c
from my_tab t
union all
select t.p, t.c
from t1
join my_tab t
on t.p = t1.c)
select p || c from t1;
SELECT file_records
into v_cnt
FROM TABLE(
print_info(
-- cursor start
cursor(
-- FIRST QUERY
with t1(p,
c) as
(select distinct null p, t.p as c
from my_tab t
union all
select t.p, t.c
from t1
join my_tab t
on t.p = t1.c)
select p || c from t1
--FIRST_QUERY END
--SECOND QUERY
--select p||c from my_tab
--SECONF QUERY END
)
-- cursor end
-- my_cursor
));
end;
当我执行块时,我收到以下错误:
ORA-32042:递归WITH子句必须在UNION ALL分支之一中直接引用自身
ORA-06512:“打印信息”第9行
ORA-06512:第17行
但是当我将代码从光标开始注释到光标结束
-- cursor start
cursor(with t1(p,
c) as
(select distinct null p, t.p as c
from my_tab t
union all
select t.p, t.c
from t1
join my_tab t
on t.p = t1.c)
select p || c from t1)
-- cursor end
和取消注释行
-- my_cursor
很好用!
如果注释第一次查询并取消注释第二次查询,则再次正常工作!
我不明白哪里出了问题 光标表达式+ANSI->native转换是一个bug 您的案例可以简化为一条SQL语句
SQL> select cursor(with t1(p, c) as (select distinct null p, t.p as c
2 from my_tab t
3 union all
4 select t.p, t.c
5 from t1
6 join my_tab t
7 on t.p = t1.c)
8 select p || c from t1) c from dual;
select cursor(with t1(p, c) as (select distinct null p, t.p as c
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-32042: recursive WITH clause must reference itself directly in one of the
UNION ALL branches
SQL> select * from table(dbms_xplan.display_cursor(format => 'basic'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
EXPLAINED SQL STATEMENT:
------------------------
select cursor(with t1(p, c) as (select distinct null p, t.p as c
from my_tab t
union all select t.p, t.c
from t1 join
my_tab t on t.p = t1.c)
select p || c from t1) c from dual
Plan hash value: 956860371
------------------------------------------------------------
| Id | Operation | Name |
------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | VIEW | |
| 2 | UNION ALL (RECURSIVE WITH) BREADTH FIRST| |
| 3 | SORT UNIQUE | |
| 4 | TABLE ACCESS FULL | MY_TAB |
| 5 | VIEW | |
| 6 | HASH JOIN | |
| 7 | RECURSIVE WITH PUMP | |
| 8 | TABLE ACCESS FULL | MY_TAB |
| 9 | FAST DUAL | |
------------------------------------------------------------
26 rows selected.
SQL> select cursor(with t1(p, c) as (select distinct null p, t.p as c
2 from my_tab t
3 union all
4 select t.p, t.c
5 from t1, my_tab t
6 where t.p = t1.c)
7 select p || c from t1) c from dual;
C
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
P|
--
1
8
7
4
12
13
42
45
46
73
84
42
45
46
14 rows selected.
SQL> select * from table(dbms_xplan.display_cursor(format => 'basic'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
EXPLAINED SQL STATEMENT:
------------------------
select cursor(with t1(p, c) as (select distinct null p, t.p as c
from my_tab t
union all select t.p, t.c
from t1, my_tab t
where t.p = t1.c) select p || c from t1) c from dual
Plan hash value: 2529699678
------------------------------------------------------------
| Id | Operation | Name |
------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | VIEW | |
| 2 | UNION ALL (RECURSIVE WITH) BREADTH FIRST| |
| 3 | SORT UNIQUE | |
| 4 | TABLE ACCESS FULL | MY_TAB |
| 5 | HASH JOIN | |
| 6 | RECURSIVE WITH PUMP | |
| 7 | TABLE ACCESS FULL | MY_TAB |
| 8 | FAST DUAL | |
------------------------------------------------------------
24 rows selected.
因此,第一个查询(使用ANSI连接语法)失败,而第二个查询(使用本机连接语法)成功完成
查询计划中的差异在于第一次查询的查看操作(ID=5)。
它告诉我们,内联视图是在查询转换期间创建的
让我们看看事件10053跟踪文件中的转换查询
select cursor(with "T1"("P", "C")
as((select "from$_subquery$_004"."QCSJ_C000000000400001_2" "P",
"from$_subquery$_004"."QCSJ_C000000000400003_3" "C"
from (select "T1"."P" "QCSJ_C000000000400000",
"T1"."C" "QCSJ_C000000000400002",
"T"."P" "QCSJ_C000000000400001_2",
"T"."C" "QCSJ_C000000000400003_3"
from "T1" "T1", "MY_TAB" "T"
where "T"."P" = "T1"."C") "from$_subquery$_004")
union all (select distinct null "P", "T"."P" "C"
from "MY_TAB" "T")) select "T1"."P" || "T1"."C"
"P||C" from "T1" "T1") "C"
from "SYS"."DUAL" "DUAL"
select cursor(with "T1"("P", "C")
as((select "T"."P" "P", "T"."C" "C"
from "T1" "T1", "MY_TAB" "T"
where "T"."P" = "T1"."C") union all
(select distinct null "P", "T"."P" "C"
from "MY_TAB" "T")) select "T1"."P" || "T1"."C"
"P||C" from "T1" "T1") "C"
from "SYS"."DUAL" "DUAL"
您可以看到,在第一次查询中,join已被转换为带有where子句的附加内联视图,如果您尝试运行第一次查询,ORA-32042将失败。我觉得这似乎是一个bug;对于递归with子句查询没有任何限制。我的Oracle支持中也没有关于该错误的内容,因此如果可以的话,您可能会收到一个服务请求。
SQL> select cursor(with t1(p, c) as (select distinct null p, t.p as c
2 from my_tab t
3 union all
4 select t.p, t.c
5 from t1
6 join my_tab t
7 on t.p = t1.c)
8 select p || c from t1) c from dual;
select cursor(with t1(p, c) as (select distinct null p, t.p as c
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-32042: recursive WITH clause must reference itself directly in one of the
UNION ALL branches
SQL> select * from table(dbms_xplan.display_cursor(format => 'basic'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
EXPLAINED SQL STATEMENT:
------------------------
select cursor(with t1(p, c) as (select distinct null p, t.p as c
from my_tab t
union all select t.p, t.c
from t1 join
my_tab t on t.p = t1.c)
select p || c from t1) c from dual
Plan hash value: 956860371
------------------------------------------------------------
| Id | Operation | Name |
------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | VIEW | |
| 2 | UNION ALL (RECURSIVE WITH) BREADTH FIRST| |
| 3 | SORT UNIQUE | |
| 4 | TABLE ACCESS FULL | MY_TAB |
| 5 | VIEW | |
| 6 | HASH JOIN | |
| 7 | RECURSIVE WITH PUMP | |
| 8 | TABLE ACCESS FULL | MY_TAB |
| 9 | FAST DUAL | |
------------------------------------------------------------
26 rows selected.
SQL> select cursor(with t1(p, c) as (select distinct null p, t.p as c
2 from my_tab t
3 union all
4 select t.p, t.c
5 from t1, my_tab t
6 where t.p = t1.c)
7 select p || c from t1) c from dual;
C
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
P|
--
1
8
7
4
12
13
42
45
46
73
84
42
45
46
14 rows selected.
SQL> select * from table(dbms_xplan.display_cursor(format => 'basic'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
EXPLAINED SQL STATEMENT:
------------------------
select cursor(with t1(p, c) as (select distinct null p, t.p as c
from my_tab t
union all select t.p, t.c
from t1, my_tab t
where t.p = t1.c) select p || c from t1) c from dual
Plan hash value: 2529699678
------------------------------------------------------------
| Id | Operation | Name |
------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | VIEW | |
| 2 | UNION ALL (RECURSIVE WITH) BREADTH FIRST| |
| 3 | SORT UNIQUE | |
| 4 | TABLE ACCESS FULL | MY_TAB |
| 5 | HASH JOIN | |
| 6 | RECURSIVE WITH PUMP | |
| 7 | TABLE ACCESS FULL | MY_TAB |
| 8 | FAST DUAL | |
------------------------------------------------------------
24 rows selected.
select cursor(with "T1"("P", "C")
as((select "from$_subquery$_004"."QCSJ_C000000000400001_2" "P",
"from$_subquery$_004"."QCSJ_C000000000400003_3" "C"
from (select "T1"."P" "QCSJ_C000000000400000",
"T1"."C" "QCSJ_C000000000400002",
"T"."P" "QCSJ_C000000000400001_2",
"T"."C" "QCSJ_C000000000400003_3"
from "T1" "T1", "MY_TAB" "T"
where "T"."P" = "T1"."C") "from$_subquery$_004")
union all (select distinct null "P", "T"."P" "C"
from "MY_TAB" "T")) select "T1"."P" || "T1"."C"
"P||C" from "T1" "T1") "C"
from "SYS"."DUAL" "DUAL"
select cursor(with "T1"("P", "C")
as((select "T"."P" "P", "T"."C" "C"
from "T1" "T1", "MY_TAB" "T"
where "T"."P" = "T1"."C") union all
(select distinct null "P", "T"."P" "C"
from "MY_TAB" "T")) select "T1"."P" || "T1"."C"
"P||C" from "T1" "T1") "C"
from "SYS"."DUAL" "DUAL"