テーブルを返すパイプライン関数を作成しました。この関数を別の関数の動的ビューのようにwith
句で使用して、特定のレコードをマークします。次に、さまざまな基準に基づいて、このクエリの結果を集計クエリで使用します。私がやりたいのはunion all
、これらの集計を一緒にすることです (それらはすべて同じソース データを使用しますが、異なる階層レベルで集計を表示するため)。
個々のレベルのデータを生成すると、正常に機能します。ただし、それらを結合しようとすると、ORA-12840 エラーが発生しますcannot access a remote table after parallel/insert direct load txn
。
(私の関数とクエリは、DB リンクを介してリモート サーバー上のテーブルを見ていることに注意してください)。
ここで何が起こっているのですか?
コードのアイデアは次のとおりです。
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 が返されます (複合 ID -フィールドキー); ただし、コードのカスタム リストを指定すると、代わりにそれらが返されます。
私は Oracle 10gR2 を使用しています。どのバージョンか正確にはわかりませんが、オフィスに戻ったら調べることができます :P