在插入更新另一个 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。
我正在尝试创建一个触发器,当拭子测试的状态从阳性变为阴性时,插入后更新另一个 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。