2017-11-26 2 views
1

Ich habe drei Tabellen zugreift:Oracle SQL - Erstellen von Trigger, die mehrere Tabellen

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 
) 

Ich versuche, einen Abzug vor dem Einsetzen in table_babysit zu schaffen, die von Babysitting ihre eigenen Kinder ein Familienmitglied verhindert. Wenn also in table_babysit die family_babysitter_id der gleichen Familien-ID wie die family_parents_id des Kindes entspricht, wäre das illegal.

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; 

Ich bin neu beim Schreiben von Triggern und ich kann nicht scheinen, mehrere Tabellen in einem Trigger zu verbinden. Was wäre der richtige Weg, um diesen Auslöser zu erstellen?

Antwort

2

Ob es ein Auslöser, eine Aussage in einem Standardverfahren, oder einfach nur eine eigenständige Abfrage ein verwenden JOIN es muss dem Formular Select folgen ... [in ...] von tabelle1 JOIN table2 auf join_condition ... Wo ein Trigger und eine Prozeduranweisung die INTO-Phrase benötigt.

In diesem Fall können Sie ein CTE verwenden, um table1 zu erstellen. Allerdings gibt es eine Komplikation hier, dass die über die notwendigen Voraussetzungen für die Verknüpfung ist eigentlich der Zustand der Auslöser verhindern versucht, aber es kann durch Umkehrung der Logik und der Auswahl, was Sie nicht wollen, zu arbeiten gemacht werden:

-- 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 

Ich bin sicher, dass es andere JOINS gibt, die das erreichen, was Sie wünschen. Ich kann gerade nicht an einen denken. Aber am leichtesten zu verstehen ist es, 2 einfache Straight-Forward-Selects zu verwenden. Also vielleicht versuchen:

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;