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