2017-11-26 1 views
1

에 액세스 만들기 트리거 나는 세 개의 테이블이 있습니다오라클 SQL 여러 테이블

table_family(
id CHAR(4) PRIMARY KEY, 
name VARCHAR(30) 
) 

table_child(
id CHAR(4) PRIMARY KEY, 
name VARCHAR(30), 
family_parents_id CHAR(4) REFERENCES table_family(id) 
) 

table_babysit(
family_babysitter_id CHAR(4) REFERENCES table_family(id), 
child_babysittee_id CHAR(4) REFERENCES table_child(id), 
hours INTEGER 
) 

나는 자신의 자녀를 탁아에서 가족을 방지 table_babysit에 삽입하기 전에 트리거를 만들려고 해요. 따라서 table_babysit에있는 family_babysitter_id가 해당 family_parents_id와 동일한 패밀리 ID와 일치하면 불법입니다.

CREATE TRIGGER check_illegal_babysit 
BEFORE INSERT 
ON table_babysit 
FOR EACH ROW 
BEGIN 
JOIN table_family ON table_family.id = family_babysitter_id 
JOIN table_child ON table_child.id = child_babysittee_id 
IF (table_family.id = table_child.family_parents_id) THEN 
RAISE_APPLICATION_ERROR(-20000,'Family cannot babysit their own children'); 
END IF; 
END; 

트리거를 작성하는 데있어서 새로운데 트리거에서 여러 테이블을 조인 할 수없는 것 같습니다. 이 방아쇠를 만드는 적절한 방법은 무엇입니까?

답변

2

는 사용하는 트리거, 표준 절차에 성명, 또는 단지 독립 쿼리하든 그 형태 선택을 따라야 가입 ... [로 ...] 표 2에 가입에서 join_condition ... 트리거 및 절차 문이 INTO 구문을 필요로하는 곳.

그의 경우 CTE를 사용하여 테이블 1을 만들 수 있습니다. 그러나, 합병증은 가입에 필요한 조건이 실제로 트리거가 방지하려고하는 상태라고 여기지만 논리를 반전하고 원하지 않는 것을 선택하여 작동하도록 만들 수 있습니다

-- define trigger (with join) 
create or replace trigger check_illegal_babysit 
before insert 
on table_babysit 
for each row 
declare 
    x varchar2(1); 

begin 
    with s as 
      (select :new.family_babysitter_id sitter 
       , :new.child_babysittee_id sittee 
      from dual 
     )  
    select null 
     into x 
     from s 
      left outer join table_family on(table_family.id = sitter) 
      left outer join table_child on(table_child.id = sittee) 
     where table_family.id = table_child.family_parents_id;    

     raise_application_error(-20000,'Family cannot babysit their own children'); 
exception 
    when no_data_found then null; 
end; 

--- Create test Family and Child rows 
insert into table_family (id, name) values('Fam1','Family1'); 
insert into table_family (id, name) values('Fam2','Family2'); 
insert into table_family (id, name) values('Fam3','Family3'); 

insert into table_child(id,name,family_parents_id) values('c1f1', 'Child1 of Family1', 'Fam1'); 
insert into table_child(id,name,family_parents_id) values('c2f1', 'Child2 of Family1', 'Fam1'); 
insert into table_child(id,name,family_parents_id) values('c3f1', 'Child3 of Family1', 'Fam1'); 
insert into table_child(id,name,family_parents_id) values('c1f2', 'Child1 of Family2', 'Fam2'); 
insert into table_child(id,name,family_parents_id) values('c2f2', 'Child2 of Family2', 'Fam2');  

-- Insert into babysit table to test trigger 
insert into table_babysit(family_babysitter_id, child_babysittee_id) values('Fam2', 'c1f1') ; -- valid 
insert into table_babysit(family_babysitter_id, child_babysittee_id) values('Fam3', 'c2f1') ; -- valid 
insert into table_babysit(family_babysitter_id, child_babysittee_id) values('Fam1', 'c3f1') ; -- invalid 

당신이 원하는 것을 성취하는 다른 조인이있을 것입니다. 나는 지금 당장 생각할 수 없다. 하지만 아마도 가장 쉬운 이해는 2 개의 간단한 직선형 선택을 사용하는 것입니다. 그럼 시도해보세요.

create or replace trigger check_illegal_babysit 
    before insert 
    on table_babysit 
    for each row 
declare 
     family_id_l table_family.id%type; 
     parents_id_l table_child.family_parents_id%type; 
begin 

    select table_family.id 
     into family_id_l 
     from table_family 
     where id = :new.family_babysitter_id; 

    select family_parents_id 
     into parents_id_l 
     from table_child 
     where id = :new.child_babysittee_id; 

    if (family_id_l = parents_id_l) then 
     raise_application_error(-20000,'Family cannot babysit their own children'); 
    end if; 
end;