繁体   English   中英

ORACLE PL / SQL在插入时更新另一个表值

[英]ORACLE PL/SQL Update another table value on insert

我想创建上持有一个表中的任何插入或更新触发DiseasesanimalNamediseaseName 我还有另一个表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。

  2. 同样,如果在添加+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);

如果是这种情况,那么您应该构建数据库,使其具有从diseasesanimals的明确外键关系。 这将确保只有有效的动物在表中。

就触发而言
:NEW表示当将新记录插入到主表中(主表在这里是您在插入表上设置触发器的表)时,它总是需要New,以便按照触发器在相对表中插入与记录相关的记录(相对表表示在触发器中您定义为在主表生效时插入/更新记录。)
:OLD表示在相对表中,它将最后插入的Id作为相对表中的新ID。 它可以用作第二张表中的外键。
希望对您的问题充满意义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM