2013-03-06 2 views
-1

table1에 삽입 트리거가 있습니다. 일부 데이터 (ID)가 허용되지 않으면 응용 프로그램 오류가 발생합니다.모든 레코드를 금지 된 목록에 삽입하십시오.

그러나 예를 들어, insert into table1 select id from table2 where id in (1,2,3)을 사용할 때 ID '3'만 허용되지 않으면 다른 ID (1 및 2)도 삽입되지 않습니다.

어떻게 이것을 극복 할 수 있습니까? 트리거 코드는 다음과 유사합니다.

CREATE OR REPLACE TRIGGER t1_before_insert BEFORE INSERT 
ON table1 
FOR EACH ROW 
DECLARE 
xx number(20); 
BEGIN 
select id into xx from blocked_id where id=:new.id; 
if :new.id=xx then raise_application_error(-20001, '--'); 
end if; 
END; 

답변

1

좋아요. 첫째, SELECT INTO ...로 NO_DATA_FOUND 예외를 발생시킬 위험이 있습니다.이 예외를 발생 시키면 전체 삽입이 삭제됩니다. 두 번째로 예외를 제기하면 전체 삽입이 중단됩니다.

은 예외를 발생시키지 않고 차단 된 표에있는 ID를 무시하십시오. 원래 아이디어를 따르려면 한 가지 방법은 아무것도 발견되지 않으면 NO_DATA_FOUND 예외를 사용하여 삽입하는 것입니다. 나는 당신의 테이블에 뷰를 만들고 이것에 INSTEAD OF trigger을 정의합니다.

우리가 설정하면 테스트 환경을 내가

(아래 참조)하지만이 방법을 사용하지 않을

:

SQL> create or replace view v_tmp_test as select * from tmp_test; 

View created. 

SQL> create or replace trigger tr_test 
    2 instead of insert on v_tmp_test 
    3 for each row 
    4 
    5 declare 
    6 
    7  l_id tmp_test.id%type; 
    8 
    9 begin 
10 
11  select id into l_id 
12  from tmp_blocked 
13  where id = :new.id; 
14 
15 exception when no_data_found then 
16  insert into tmp_test values (:new.id); 
17 end; 
18/

Trigger created. 

SQL> show error 
No errors. 

SQL> insert into v_tmp_test 
    2 select level 
    3  from dual 
    4 connect by level <= 3; 

3 rows created. 

SQL> select * from tmp_test; 

     ID 
---------- 
     1 
     2 

:

SQL> create table tmp_test (id number); 

Table created. 

SQL> create table tmp_blocked (id number); 

Table created. 

SQL> insert into tmp_blocked values (3); 

1 row created. 

는 그런 다음 사용할 수 있습니다 내가 말했듯이, 나는 트리거를 사용하지 않을 것입니다. 더 효율적인 방법은 MERGE을 사용하는 것입니다. 위와 동일한 설정을 사용하십시오. 데이터 무결성이 정말로 무엇을하지 않습니다 -

SQL> merge into tmp_test o 
    2 using (select a.id 
    3   from (select level as id 
    4      from dual 
    5     connect by level <= 3) a 
    6   left outer join tmp_blocked b 
    7    on a.id = b.id 
    8   where b.id is null 
    9    ) n 
10  on (o.id = n.id) 
11 when not matched then 
12 insert values (n.id); 

2 rows merged. 

SQL> 
SQL> select * from tmp_test; 

     ID 
---------- 
     1 
     2 

이보다 쉽게 ​​대안은 그냥 내가 정말이 방법으로 트리거의 사용 및 오류를 싫어하는 MINUS

insert into tmp_test 
select level 
    from dual 
connect by level <= 3 
    minus 
select id 
    from tmp_banned 
0

를 사용하는 것 트리거가 필요합니다. 이것은 응용 프로그램 코드에 포함되어야하는 응용 프로그램의 일부인 것처럼 보입니다. 아마도 테이블에 삽입하기위한 API 역할을하는 프로 시저에있을 것입니다.

관련 문제