我有三张桌子:
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;
我是新手编写触发器,我似乎无法在触发器中加入多个表。创建此触发器的正确方法是什么?
答案 0 :(得分:2)
无论是触发器,标准过程中的语句,还是仅使用JOIN的独立查询,它都必须遵循表单 在join_condition上从 table1 JOIN table2 中选择... [into ...] ... 触发器和程序声明需要INTO短语的地方。
在他的情况下,您可以使用CTE来创建 table1 。但是,这里有一个复杂因素,连接所需的条件实际上是触发器试图阻止的条件,但是可以通过反转逻辑并选择你不想要的东西来使其工作:
-- 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
我确信还有其他的JOINS可以达到你想要的效果。我现在想不出一个。但也许最容易理解的是使用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;