[英]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.