我正在尝试创建一个触发器,以便在拭子测试的状态从正变为负时,在插入后更新另一个表。
我已经创建了此触发器,但是问题是,每当有一个拭子为负的用户时,即使该用户从未为正,也将用户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
答案 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。