[英]ORACLE PL/SQL Update another table value on insert
我想创建上持有一个表中的任何插入或更新触发Diseases
与animalName
和diseaseName
。 我还有另一个表Animals
,其中包含诸如animalName
(这是一个主键;请不要对设计进行评论,因为它不是我的)之类的信息,以及他拥有的amountOfDisease
。 我希望在“ Diseases
表中插入,更新或删除后,“ Diseases
”数量自动更新。
我很难理解如何获取当前的animalName
以便更新他的amountOfDisease
。
到目前为止,我有这个:
CREATE OR REPLACE TRIGGER update_animal_diseases
AFTER INSERT OR UPDATE OR DELETE ON Diseases
FOR EACH ROW
BEGIN
UPDATE Animals SET amountOfDisease = amountOfDisease + 1
WHERE animalName = :NEW.animalName;
END;
/
哪个可以编译但不起作用,因为Animals
的值永远不会在将某些内容插入Diseases
更新。 我也试过这个:
CREATE OR REPLACE TRIGGER update_animal_diseases
AFTER INSERT OR UPDATE ON Diseases
FOR EACH ROW
DECLARE
DiseasesCount INTEGER;
BEGIN
SELECT COUNT(*) INTO DiseasesCount
FROM Diseases
WHERE animalName = :OLD.animalName;
UPDATE Animals SET amountOfDisease = DiseasesCount WHERE animalName = :OLD.animalName;
END;
/
如您所见,我也不太了解:NEW和:OLD是什么。 我该如何解决我的问题,那就是在Diseases
表的任何修改后更新动物的amountOfDisease
?
明确地说,我对Diseases
插入一无所获。 据我所知,没有任何反应。
我看到两个可能的原因。
在第一个版本中,即使删除,您也总是会添加+1。
同样,如果在添加+1后记录上的amountofdisease字段为null,则无论如何它将为null。
也许这样的事情应该为您工作。
表:
CREATE TABLE animals
( animalname VARCHAR2 (10),
amountofdisease NUMBER);
CREATE TABLE diseases
( animalname VARCHAR2 (10),
diseasename VARCHAR2 (20));
触发:
CREATE OR REPLACE TRIGGER apps.diseases_aiud1
BEFORE DELETE OR INSERT OR UPDATE
ON diseases
REFERENCING NEW AS new OLD AS old
FOR EACH ROW
DECLARE
BEGIN
IF INSERTING
THEN
UPDATE animals
SET amountofdisease = NVL (amountofdisease, 0) + 1
WHERE animalname = :new.animalname;
ELSIF DELETING
THEN
UPDATE animals
SET amountofdisease = NVL (amountofdisease, 0) - 1
WHERE animalname = :old.animalname;
ELSIF UPDATING
THEN
UPDATE animals
SET amountofdisease = NVL (amountofdisease, 0) + 1
WHERE animalname = :new.animalname;
UPDATE animals
SET amountofdisease = NVL (amountofdisease, 0) - 1
WHERE animalname = :old.animalname;
END IF;
END diseases_aiud1;
/
注意根据事件的使用:new和:old。
加载样本动物:
insert into animals values ('jaguar',0);
insert into animals values ('capibara',0);
insert into animals values ('fox',0);
commit;
测试1插入
insert into diseases values
('jaguar','pneumonia');
insert into diseases values
('jaguar','epistaxis');
commit;
select *
from animals;
结果1:
1 row created.
1 row created.
Commit complete.
ANIMALNAME AMOUNTOFDISEASE
---------- ---------------
jaguar 2
capibara 0
fox 0
3 rows selected.
测试2删除:
delete from diseases
where animalname = 'jaguar' and diseasename = 'pneumonia'
;
insert into diseases values
('fox','hydrophobia');
结果2:
ANIMALNAME AMOUNTOFDISEASE
---------- ---------------
jaguar 1
capibara 0
fox 1
测试3更新:
update diseases
set animalname = 'capibara'
where animalname = 'fox';
结果3:
ANIMALNAME AMOUNTOFDISEASE
---------- ---------------
jaguar 1
capibara 1
fox 0
附带说明,应建议编写一个软件包以处理此逻辑。 触发器很棘手,最难维护,在某些情况下可能导致意外结果。
问候,
如果我不得不推测,那么对于“ Diseases
所有动物,“ Animals
中都没有匹配的行。 您可以通过执行以下操作找到它们:
select d.*
from diseases d
where not exists (select 1 from animals a where a.animal = d.animal);
如果是这种情况,那么您应该构建数据库,使其具有从diseases
到animals
的明确外键关系。 这将确保只有有效的动物在表中。
就触发而言
:NEW表示当将新记录插入到主表中(主表在这里是您在插入表上设置触发器的表)时,它总是需要New,以便按照触发器在相对表中插入与记录相关的记录(相对表表示在触发器中您定义为在主表生效时插入/更新记录。)
:OLD表示在相对表中,它将最后插入的Id作为相对表中的新ID。 它可以用作第二张表中的外键。
希望对您的问题充满意义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.