所以我有两张表:JOBS 和TASKS。
TASKS 表有一个 TAKS_STATUS 列,它存储状态的进展(例如,“提交”、“已提交”、“已授权”、“已完成”)。
JOBS 表有一个JOB_STATUS 列,它是TASKS 表中TASK_STATUS 列的汇总(即最小状态)。JOBS 表还有一个 TASK_COUNT 值,其中包含与 Job 关联的 TASKS 的数量。
作业可以有一个或多个任务:每个表中的 JOB_ID 链接它们。
在 DB2 中,我有一系列简单的触发器来汇总这种状态;这是中间的一个:
create or replace trigger JOB_AUTHORED
after update of TASK_STATUS on TASKS
referencing NEW as N
for each row
when (TASK_STATUS = 'Authored')
update JOBS
set JOB_STATUS = 'Authored'
where JOBS.JOB_ID = N.JOB_ID
and TASK_COUNT=(
select count(0) from TASKS
where TASKS.JOB_ID = N.JOB_ID
and TASKS.TASK_STATUS in ('Authored','Completed'))
这在 DB2 中工作得很好,因为触发器与触发事件在同一个工作单元中运行,因此它可以看到工作单元的未提交更改,并且可以计算刚刚发生的 TASK_STATUS 更改而不会遇到行锁。
这是 Oracle 中翻译后的触发器:
create or replace trigger JOB_AUTHORED
after update of TASK_STATUS on TASKS
for each row
when (NEW.TASK_STATUS = 'Authored')
BEGIN
update JOBS
set JOB_STATUS='Authored'
where JOBS.JOB_ID = :NEW.JOB_ID and TASK_COUNT=(
select count(0) from TASKS
where TASKS.JOB_ID = :NEW.JOB_ID
and TASKS.TASK_STATUS in ('Authored','Completed'));
END;
在 Oracle 中,这失败了:
ORA-04091: table MYSCHEMA.TASKS is mutating, trigger/function may not see it#012ORA-06512: at "MYSCHEMA.JOB_AUTHORED", line 1#012ORA-04088: error during execution of trigger 'MYSCHEMA.JOB_AUTHORED'#012] [query: UPDATE TASKS SET TASK_STATUS=:1 where TASK_ID=:2
显然,Oracle 的触发器不在同一上下文中运行,看不到未提交的触发更新,因此永远无法计算包括触发行在内的特定状态的任务数。
我想我可以将 AFTER 触发器更改为 INSTEAD OF 触发器并更新触发器内的 TASK_STATUS(以及 JOB_STATUS)(因此作业更新可以看到任务更新),但我会遇到同样的错误吗?也许不是第一个任务更新,但是如果触发程序在提交之前更新了一堆任务怎么办:当第二个任务更新时会发生什么?
我还考虑过删除触发器并让程序扫描活动作业以了解其任务的状态,但这似乎不优雅。
在 Oracle 中这样的最佳实践是什么?