在联合中使用时,Oracle管道功能无法访问远程表(ORA-12840)

时间:2012-08-20 16:28:01

标签: oracle plsql

我创建了一个返回表格的流水线函数。我在另一个函数中使用此函数,如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

1 个答案:

答案 0 :(得分:1)

说实话,不知道问题的来源,但最简单的解决方法 - 创建一个临时表,并使用流水线函数中的值填充它,并使用WITH子句中的表。当然应该创建临时表但是我很确定你会得到严重的性能转换,因为动态采样不适用于没有技巧的流水线函数。

P.S。问题可以通过标记为(从表中选择/ * + INLINE / id(getMatches('OK'))来修复,但肯定不是你要找的东西,所以我的建议被确认为做了类似'insert / + APPEND * /'的内容。