ORACLE PL / SQL更新插入

时间:2017-10-21 13:27:20

标签: sql oracle triggers

我正在尝试在包含Diseases animalNamediseaseName的表格上的任何插入或更新上创建触发器。 我有另一张表Animals,其中包含animalName之类的信息(这是主键;不要对设计发表评论,因为它不是我的),以及{{1} } 他有。 我希望在amountOfDisease表中插入,更新或删除时,会自动更新疾病数量。

我很难理解如何获取当前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

正如你所看到的,我也不太了解:NEW和:OLD是什么。如何解决我的问题,即在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; / 表的任何修改上更新动物amountOfDisease

要明确的是,我在插入Diseases时所得到的只是一无所获。就我所知,没有任何事情发生。

3 个答案:

答案 0 :(得分:1)

我看到两个可能的原因。

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

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

  3. 也许这样的事情对你有用。

    表:

    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
    

    作为旁注,应该建​​议编写一个包来处理这个逻辑。触发器很棘手,难以维护,并且在某些情况下可能会导致意外结果。

    此致

答案 1 :(得分:0)

如果我不得不推测,Animals中的所有动物的Diseases中都没有匹配的行。你可以这样做:

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

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

答案 2 :(得分:0)

至于触发器,
:NEW表示当插入到主表中的新记录时(主表在这里表示在插入时设置触发器的表)它总是需要新的我将根据相对表中的触发器插入记录相关记录(相对表表示在触发器中)您定义为在主表受影响时插入/更新记录。)
:OLD表示在相对表中它最后插入我作为相对表中的新id。它可以用作第二表中的foriegn键 我希望这对你的问题意义重大。