One possible approach is to force execution of the JOIN on the remote site using the DRIVING_SITE hint:
INSERT INTO pst
SELECT /*+DRIVING_SITE(abc)*/
remote.col1, remote.col2, remote.col3, remote.col4
FROM
abc@dblink remote,
xyz local
WHERE remote.col1=local.col1
AND remote.col2=local.col2;
(I seem to recall there's a limitation when doing an INSERT
instead of a plain SELECT
, but I can't find it in the docs right now - you might have to switch to a PL/SQL procedure that does a cursor fetch from remote and then performs the INSERT
locally to benefit from the hint).
UPDATE
Oracle will indeed ignore the DRIVING_SITE
hint when doing an INSERT
into a local table. Jonathan Lewis has an interesting article explaining the reasons for this.
So, you can:
- switch to a PL/SQL procedure that does a
SELECT .. BULK COLLECT
with the DRIVING_SITE
hint and performs the local INSERT
- create a join view remotely, and use that view for the
INSERT
UPDATE 2
Here's a complete solution using the PL/SQL approach; it uses an object type and an associated collection (I've used a dummy query for input that simply generates 9500 rows instead of the original DB link one, but adapting it is pretty straightforward):
create table pst(col1 number, col2 number, col3 number, col4 number);
create type pst_t as object (
col1 number,
col2 number,
col3 number,
col4 number);
create type pst_table_t as table of pst_t;
declare
v_coll pst_table_t;
C_LIMIT constant pls_integer := 1000;
cursor v_cur is
select
pst_t(level, level*2, level*3, level*4)
from dual
connect by level <= 9500;
begin
open v_cur;
loop
fetch v_cur bulk collect into v_coll limit C_LIMIT;
insert into pst(col1,col2,col3,col4)
select col1,col2,col3,col4 from table(v_coll);
exit when v_coll.count < C_LIMIT;
end loop;
end;