2013-02-15 3 views
0

가능한지 모르지만 임시 테이블의 레코드를 일반 테이블로 복사하려고합니다. 문제는 일부 레코드가 검사 제약 조건을 위반할 수 있으므로 가능한 모든 것을 삽입하고 잘못된 레코드에 대해 다른 위치에서 오류 로그를 생성하려고합니다.오라클의 check 제약 조건에 따라 테이블이 유효 할 경우에만 테이블간에 레코드를 복사 할 수 있습니까?

나는 실행하면 : 어떤 기록이 어떤 제약 조건을 위반하는 경우

INSERT INTO normal_table 
    SELECT ... FROM temp_table 

아무것도 삽입하지 될 것이다. 루프를 만들고 수동으로 하나씩 삽입 할 수는 있지만 성능이 떨어질 것이라고 생각합니다.

시 : 가장 단순한 형태의

EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG('NORMAL_TABLE'); 
INSERT INTO normal_table 
    SELECT ... FROM temp_table 
    LOG ERRORS REJECT LIMIT UNLIMITED; 

: 나는 오라클 10gR2의에서 오라클 9

답변

3

함께 작동하는 솔루션을하고 싶습니다 가능하다면, 당신은 log errors clause를 사용할 수 있습니다. CREATE_ERROR_LOG 단계 here

SELECT ora_err_mesg$ 
FROM err$_normal_table; 

더 : 당신은 당신이 무엇을 가지고 오류를 볼 수 있습니다. 테스트 불통 (PLS-00436을 피하기 위해) :


나는이 방법은 9i의에서 작동 생각하지만,에 테스트하기 위해 사용할 수있는 인스턴스를 가지고 있지 않기 때문에 이것은 실제로 11gR2에
업데이트를 실행

create table normal_table(id number primary key); 
create table temp_table(id number); 
create table err_table(id number, err_code number, err_msg varchar2(2000)); 

insert into temp_table values(42); 
insert into temp_table values(42); 
: 난 그냥 데모 목적을 위해 수행 한 대신 id의 모든 실제 열로

declare 
    type t_temp_table is table of temp_table%rowtype; 
    l_temp_table t_temp_table; 
    l_err_code err_table.err_code%type; 
    l_err_msg err_table.err_msg%type; 
    l_id err_table.id%type; 

    cursor c is select * from temp_table; 

    error_array exception; 
    pragma exception_init(error_array, -24381); 
begin 
    open c; 
    loop 
     fetch c bulk collect into l_temp_table limit 100; 
     exit when l_temp_table.count = 0; 

     begin 
      forall i in 1..l_temp_table.count save exceptions 
       insert into normal_table 
       values l_temp_table(i); 
     exception 
      when error_array then 
       for j in 1..sql%bulk_exceptions.count loop 
        l_id := l_temp_table(sql%bulk_exceptions(j).error_index).id; 
        l_err_code := sql%bulk_exceptions(j).error_code; 
        l_err_msg := sqlerrm(-1 * sql%bulk_exceptions(j).error_code); 
        insert into err_table(id, err_code, err_msg) 
        values (l_id, l_err_code, l_err_msg); 
       end loop; 
     end; 
    end loop; 
end; 
/

: 9i에의 '아무튼 당신이 (있기 때문에 이들에 대한 개별 인서트) 예외의 많은 경우, 더 코딩 속도가 느린 -

그런 다음

select * from normal_table; 

     ID 
---------- 
     42 

column err_msg format a50 
select * from err_table; 

     ID ERR_CODE ERR_MSG           
---------- ---------- -------------------------------------------------- 
     42   1 ORA-00001: unique constraint (.) violated   

이 적은 몇 수준에 만족 ... 위의 익명 블록을 실행 어떤 제약 조건을 위반했는지 (또는 다른 오류 세부 정보) 보여 주며, 롤백하면 오류를 유지하지 않습니다. 문제가 될 경우 자치 트랜잭션을 호출하여 여기에서 의심합니다.

당신이 limit 절에 대해 걱정하지 데이터의 작은 충분한 볼륨이있는 경우는 조금 단순화 할 수 있습니다 :

declare 
    type t_temp_table is table of temp_table%rowtype; 
    l_temp_table t_temp_table; 
    l_err_code err_table.err_code%type; 
    l_err_msg err_table.err_msg%type; 
    l_id err_table.id%type; 

    error_array exception; 
    pragma exception_init(error_array, -24381); 
begin 
    select * bulk collect into l_temp_table from temp_table; 

    forall i in 1..l_temp_table.count save exceptions 
     insert into normal_table 
     values l_temp_table(i); 
exception 
    when error_array then 
     for j in 1..sql%bulk_exceptions.count loop 
      l_id := l_temp_table(sql%bulk_exceptions(j).error_index).id; 
      l_err_code := sql%bulk_exceptions(j).error_code; 
      l_err_msg := sqlerrm(-1 * sql%bulk_exceptions(j).error_code); 
      insert into err_table(id, err_code, err_msg) 
      values (l_id, l_err_code, l_err_msg); 
     end loop; 
end; 
/

하는 9i의 문서는 더 이상 온라인 것 같다,하지만하지 않습니다 이것은 new-features document에 있으며 많은 사람들이 그것에 대해 글을 남겼습니다. asked about here before too입니다.

+0

내가 언급 한 것을 잊어 버렸습니다. 오라클 9에서도 작동하는 솔루션이 필요합니다. 내 잘못입니다. 질문을 수정합니다. 그러나이 솔루션은 매우 좋은 것처럼 보입니다. 더 이상의 대답을 얻지 못하면 대답을 사용하고 고려해 볼 것입니다. –

0

점검 제한 조건에만 특히 관심이있는 경우, 데이터 사전에서 대상 점검 제한 조건의 정의를 읽고이를 사용하여 소스 테이블에서 데이터를 추출하는 쿼리에 조건 자로 적용하십시오 동적 SQL.

을 감안할 때 :

create table t1 (
    col1 number check (col1 between 3 and 10)) 

할 수 있습니다 :

select constraint_name, 
     search_condition 
from user_constraints 
where constraint_type = 'C' and 
     table_name = 'T1' 

결과의 존재 :

"SYS_C00226681"가 그것의에서

"COL1 3과 10 사이" " 코딩의 단순한 문제 "라고 말하면서,이 방법은 오라클의 모든 버전에서 작동 할 것입니다. 가장 효율적인 f}은 아마도 점검 가능한 조건부 술어를 적용하는 CASE 문의 결과에 따라 행을 의도 된 목표 테이블이나 오류 로깅 테이블로 보내도록 다중 테이블 삽입기를 사용하는 것입니다.