插入后创建触发器,以更新另一个表

时间:2020-05-07 22:42:43

标签: sql oracle select plsql database-trigger

我正在尝试创建一个触发器,以便在拭子测试的状态从正变为负时,在插入后更新另一个表。

我已经创建了此触发器,但是问题是,每当有一个拭子为负的用户时,即使该用户从未为正,也将用户ID复制到表中。也许我可以比较一下日期吗?

Create or replace trigger trigger_healed 
After insert on swab_test
For each row
Begin
  if :new.result = 'Negative' then
     UPDATE illness_update
     SET illness_update.state = 'healed'
     WHERE illness_update.id_user = :new.id_user;
 end if;
end;

这是我想要得到的结果。

SWAB_TEST

id_user id_swab swab_result   date
1       test1   'positive'  May-01-2020
1       test1   'negative'  May-08-2020
2       test2   'negative'  May-02-2020

ILLNESS_UPDATE

id_user  state     date
1       'healed'  May-08-2020

2 个答案:

答案 0 :(得分:2)

您要的内容将要求触发器查看插入表中的现有行-默认情况下无法完成,因为触发器无法对其触发的表进行操作。

与其尝试解决该问题,不建议仅创建一个视图以生成所需的结果。这样一来,您就可以始终以最新的视角查看数据,而无需支付任何维护费用:

create view illness_update_view(id_user, state, date) as
select id_user, 'healed', date
from (
    select 
        s.*, 
        lag(swab_result) over(partition by id_user order by date) lag_swab_result
    from swab_test s
) s
where lag_swab_result = 'positive' and swab_result = 'negative'

该视图使用窗口函数lag()来恢复每行(每个用户)的“上一个”结果。保留表示从正值到负值的过渡的行。

答案 1 :(得分:1)

@GMB表示您无法使用标准的行前/行后触发器来执行您要的操作,因为它不能引用swab_test,因为这是导致触发器触发的表(这将导致ORA-04091变异表错误)。但是您可以在复合触发器(或After语句)中执行此操作。但在此之前,我认为您的数据模型存在致命缺陷。

您已经建立了用于多种拭子测试的功能。对此的逻辑扩展是每个id_swab针对不同条件进行测试,或针对相同条件进行不同测试。但是,测试(id_swab)不在您的疾病更新表中。这意味着,如果在获得先前的肯定结果之后,任何测试变为否定结果,则用户会从所有测试中恢复健康。要更正此问题,您需要添加一个包含id_swab id来进行修复。由于GMB提供了最好的解决方案,因此我将在此进行扩展。首先删除表Illness_update。然后创建Illness_update作为视图。 (注意:在回答您的问题时,您不需要触发视图,所有必要的操作都在swab_test中;请参见lag windowed function

create view illness_update(id_user, state, swab_date) as
select id_user,  id_swab, 'healed' state,swab_date
from (
    select 
        s.* 
     ,  lag(swab_result) over(partition by id_user, id_swab
                             order by id_user, id_swab, swab_date) as lag_swab_result
    from swab_test s 
) s
where lag_swab_result = 'positive'
  and swab_result = 'negative'; 

现在,如上所述,如果您的作业需要使用触发器,请参阅fiddle注意:我不使用日期(或任何数据类型)作为列名。在这里,我在所有实例中都使用swab_date。

相关问题