我创建了一个返回表格的流水线函数。我在另一个函数中使用此函数,如with
子句中的动态视图,以标记某些记录。然后,我根据各种条件在聚合查询中使用此查询的结果。我想要做的是union all
这些聚合在一起(因为它们都使用相同的源数据,但在不同的层次级别显示聚合)。
当我为各个级别生成数据时,它可以正常工作。但是,当我尝试将它们组合在一起时,我收到一个ORA-12840错误:cannot access a remote table after parallel/insert direct load txn
。
(我应该注意,我的函数和查询正在通过数据库链接查看远程服务器上的表。)
任何想法在这里发生了什么?
以下是代码的概念:
function getMatches(criteria in varchar2) return myTableType pipelined;
...此函数基本上执行一些动态SQL,它引用远程表,作为引用游标并吐出结果。
然后,因子查询类似于:
with marked as (
select id from table(getMatches('OK'))
),
fullStats as (
select mainTable.id,
avg(nvl2(marked.id, 1, 0)) isMarked,
sum(mainTable.val) total
from mainTable
left join marked
on marked.id = mainTable.id
group by mainTable.id
)
第一个因素的原因是速度 - 如果我内联它,在连接中,查询进行得非常慢 - 但不管怎样,它都不会改变导致该问题的任何因素的状态。异常。
然后,说完整的概述,我会这样做:
select sum(total) grandTotal
from fullStats
...或isMarked
的概述:
select sum(total) grandTotal
from fullStats
where isMarked = 1
这些单独工作很好(我的伪代码可能错误或过于简单,但你明白了),但只要我union all
他们在一起,我就会收到ORA-12840错误:(
编辑根据请求,这是我的函数的模糊版本:
function getMatches(
search in varchar2)
return idTable pipelined
as
idRegex varchar2(20) := '(05|10|20|32)\d{3}';
searchSQL varchar2(32767);
type rc is ref cursor;
cCluster rc;
rCluster idTrinity;
BAD_CLUSTER exception;
begin
if regexp_like(search, '^L\d{3}$') then
searchSQL := 'select distinct null id1, id2_link id2, id3_link id3 from anotherSchema.linkTable@my.remote.link where id2 = ''' || search || '''';
elsif regexp_like(search, '^' || idRegex || '(,' || idRegex || || ')*$') then
searchSQL := 'select distinct null id1, id2, id3 from anotherSchema.idTable@my.remote.link where id2 in (' || regexp_replace(search, '(\d{5})', '''\1''') || ')';
else
raise BAD_CLUSTER;
end if;
open cCluster for searchSQL;
loop
fetch cCluster into rCluster;
exit when cCluster%NOTFOUND;
pipe row(rCluster);
end loop;
close cCluster;
return;
exception
when BAD_CLUSTER then
raise_application_error(-20000, 'Invalid Cluster Search');
return;
when others then
raise_application_error(-20999, 'API' || sqlcode || chr(10) || sqlerrm);
return;
end getMatches;
它非常简单,专为具有有限访问权限的API而设计,在复杂性方面(因此将逗号分隔的字符串作为可能的有效参数传递):如果提供分组代码,则返回链接ID(它是复合的,3字段的密钥);但是,如果您提供自定义代码列表,则只返回这些代码。
我在Oracle 10gR2上;我不知道究竟是哪个版本,但是当我回到办公室时,我可以查一查:P
答案 0 :(得分:1)
说实话,不知道问题的来源,但最简单的解决方法 - 创建一个临时表,并使用流水线函数中的值填充它,并使用WITH子句中的表。当然应该创建临时表但是我很确定你会得到严重的性能转换,因为动态采样不适用于没有技巧的流水线函数。
P.S。问题可以通过标记为(从表中选择/ * + INLINE / id(getMatches('OK'))来修复,但肯定不是你要找的东西,所以我的建议被确认为做了类似'insert / + APPEND * /'的内容。