2012-05-10 3 views
2

데이터베이스 링크를 통해 사용되는 경우 오라클에 forall .. insert을 사용하는 것을 금지하는 구현 제한 사항이있는 것처럼 보입니다. 아주이 혼동이 다음 오류와 9i에 실패 데이터베이스 링크를 통한 대량 삽입 제한 극복

connect schema/[email protected] 

create table tmp_ben_test (
    a number 
, b number 
, c date 
, constraint pk_tmp_ben_test primary key (a, b) 
    ); 

Table created. 

connect schema/[email protected] 
Connected. 

declare 

    type r_test is record (a number, b number, c date); 
    type t__test is table of r_test index by binary_integer; 
    t_test t__test; 

    cursor c_test is 
    select 1, level, sysdate 
     from dual 
    connect by level <= 10 
      ; 

begin 

    open c_test; 
    fetch c_test bulk collect into t_test; 

    forall i in t_test.first .. t_test.last 
    insert into [email protected] 
    values t_test(i) 
      ; 

    close c_test; 

end; 
/

:

ERROR at line 1: ORA-01400: cannot insert NULL into ("SCHEMA"."TMP_BEN_TEST"."A") ORA-02063: preceding line from DB1 ORA-06512: at line 18

의 경우는 11g에 확인 후 내가 실현이 구현 제한했다이 보여주기 위해 간단한 예입니다 .

for i in t_test.first .. t_test.last loop 
    insert into [email protected] 
    values t_test(i); 
end loop; 

하지만, 오히려 가능한 모든 경우에 하나의 삽입에 그것을 아래로 유지하는 것이 라운드

ERROR at line 18: ORA-06550: line 18, column 4: PLS-00739: FORALL INSERT/UPDATE/DELETE not supported on remote tables

진짜로 확실한 방법은에 forall ..을 변경하는 것입니다. Tom Kyte suggests the use of a global temporary table. 데이터를 GTT에 삽입 한 다음 DB 링크를 통해 삽입하면 이미 사용자 정의 유형에있는 데이터 집합에 대한 엄청난 과잉 상태 인 것처럼 보입니다.

이 예제를 명확히하기 위해 실제로 일어나는 것과 비교하여 극히입니다. 우리가 간단한 insert into을 할 수있는 방법이 없으며 GTT에서 모든 작업을 수행 할 수있는 방법이 없습니다. 코드의 대부분은 사용자 정의 유형으로 수행해야합니다.

DMLy가 더 간단하거나 더 적은 방법이 있습니까?

+0

GTT 이상을 시도해 보셨습니까? 11g의 성능을 비교하십시오. 과도기는 아니지만 날짜를 이동하는 빠른 방법이라고 생각합니다. –

+0

아니요. 시도하지 않았습니다. 다른 옵션이 없다면 분명히 알 수 있습니다. 기억에서 무언가를 취하는 것이 이상하게 보입니다. 다른 메모리로 이동 한 다음 DML을 수행하십시오. 좀 더 단순한 솔루션을 원했습니다. 존재하는 경우. – Ben

+0

조금만 생각해보십시오. GTT 부분은 순수한 SQL이며 빠른 것입니다 (dblink 패널티). 느린 것은 배열과 함께 ps/sql 부분입니다 ... –

답변

2

원격 데이터베이스에서 어떤 제한 사항이 발생합니까? 거기에 객체를 만들 수 있다면 해결 방법이 있습니다. 원격 데이터베이스에서 컬렉션 유형을 만들고 컬렉션을 매개 변수로 사용하고 FORALL 문을 실행하는 프로 시저를 만듭니다.

+0

아무 제한이 없습니다; 이것들은 단지 DB를 처리하고 있으며 외부 세계에 연결되어 있지 않습니다. 그게 무슨 뜻인지 알기까지 몇 초 걸렸습니다. 매개 변수로 타입을 취하고 저를 위해 insert를 수행하는 db2'에서 'db1'에 대한 프로 시저를 실행합니까? – Ben

1

db2에서 t__test/r_test 유형을 작성한 후 db1에서 공용 동의어를 작성하면 db1에서 db2로 t_table을 채우고 db1로 리턴하는 프로 시저를 호출 할 수 있어야합니다. 그런 다음 로컬 테이블에 삽입 할 수 있어야합니다.

익명 블록이 아닌 실제 유형에서 패키지 유형 및 프로 시저를 사용한다고 가정합니다.

또한 큰 데이터 세트의 경우에는 이상적인 솔루션이 아니므로 GTT 또는 이와 유사한 것이 더 좋을 것입니다.