3

我创建了一个返回表的流水线函数。我使用这个函数就像在另一个函数中的动态视图一样,在一个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

4

1 回答 1

2

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

ps 这个问题可以通过标记为 ( select /*+ INLINE / id from table(getMatches('OK'))) 来解决,但肯定不是你要找的东西,所以我的建议得到了证实就像'插入/ + APPEND * /'里面'。

于 2012-08-20T16:52:14.937 回答