2017-10-21 103 views
0

我想创建一个触发器上的任何插入或更新的表上,其中包含DiseasesanimalNamediseaseName。 我有另一张表,Animals,其中保存的信息如animalName(这是一个主键;不要评论设计,因为它不是我的),和他的amountOfDisease。 我希望在插入,更新或删除Diseases表格时,疾病的数量会自动更新。ORACLE PL/SQL插入更新另一个表值

我很难理解如何获取当前的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就是没有。据我所知,没有任何反应。

+0

@GordonLinoff正如我在帖子结尾所说,没有任何反应,值没有正确更新。 – user96649

回答

0

如果我不得不推测,Diseases中所有动物的Animals没有匹配的行。您可以通过找到这些:

select d.* 
from diseases d 
where not exists (select 1 from animals a where a.animal = d.animal); 

如果是这种情况,那么你应该构建数据库有一个明确的外键关系从diseasesanimals。这将确保只有有效的动物在桌子上。

0

至于触发,
:新手段当插入到你的主表的新记录(主表在这里意味着,你将在插入触发器表),它需要不断有新的我倒是插入记录相关的记录为每个触发器在相对表中(相对表意味着在触发器中定义为在主表生效时插入/更新记录)。
:OLD表示它在最近插入的相对表中,我将它作为相对表中的新ID。它可以用作第二个表中的foriegn键。
我希望这是完全适合你的问题。

1

我看到两个可能的原因。

  1. 在第一个版本中,您总是添加+1,即使在删除时也是如此。

  2. 另外,如果添加+1后记录中的amountofdisease字段为空,则无论如何都将为空。

也许这样的事情应该适合你。

表:

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; 
/

注意去使用新的和。

加样品动物:

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 

作为一个侧面说明,应当建议,以处理这个写一个包逻辑。触发器很棘手,最难维护,并且在某些情况下可能导致意想不到的结果。

Regards,