在插入更新另一个 table 后创建触发器

Create a trigger after insert that update another table

我正在尝试创建一个触发器,当拭子测试的状态从阳性变为阴性时,插入后更新另一个 table。

我已经创建了这个触发器,但问题是每次有一个用户的拭子呈阴性时,用户 ID 就会被复制到 table,即使这个用户从未呈阳性。也许,我要比较日期吗?

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

您要求的内容需要触发器查看正在插入的 table 中的现有行 - 默认情况下无法完成,因为触发器无法操作 table它开火。

与其尝试解决这个问题,我建议您简单地创建一个视图来生成您想要的结果。这让您始终了解最新的数据,而无需任何维护成本:

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'

视图使用 window 函数 lag() 恢复每行(每个用户)的 "previous" 结果。保留表示从正面结果到负面结果的转换的行。

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

您已经建立了多次拭子测试的能力。对此的逻辑扩展是每个 id_swab 测试不同的条件,或不同的测试相同的条件。但是,测试 (id_swab) 不在您的疾病更新 table 中。这意味着如果任何测试在获得先前的阳性结果后变为阴性结果,则用户可以从所有测试中恢复过来。要更正此问题,您需要包含 id_swab id 来做出修复决定。由于 GMB 提供了最佳解决方案,我将对此进行扩展。首先删除 table Illness_update。然后创建 Illness_update 作为视图。 (注意:在回答您的问题时,您不需要视图的触发器,所有必要的东西都在 swab_test 中;参见

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。