我正在尝试在oracle 12c中创建一个触发器,如果插入的值包含特定值,它将执行过程。
我想要做的是在某些表(EVENTS,MARKS,STAGE)全部刷新之后,我才希望触发器运行REFRESH_MVS();程序。
刷新后,它们将存储在COUNTS表中。所以我正在检查COUNTS中的新INSERT是否有关键字:EVENTS,MARKS,STAGE。
这是这样做的吗?
CREATE or replace TRIGGER MV_REFRESH
AFTER INSERT ON COUNTS
FOR EACH ROW
DECLARE
MODEL_NAME varchar2(20);
BEGIN
select MODEL INTO MODEL_NAME from COUNTS;
IF(MODEL_NAME = 'EVENTS' AND MODEL_NAME = 'MARKS' AND MODEL_NAME = 'STAGE')
THEN
REFRESH_MVS();
END IF;
END;
如果我运行INSERT成功编译它:
INSERT INTO COUNTS
values ('EVENTS', '11658495', '0.11', '17-MAR-14', '17-MAR-14');
它抛出错误:
Error starting at line 3 in command:
INSERT INTO COUNTS
values ('EVENTS', '11658495', '0.11', '17-MAR-17', '17-MAR-17')
Error report:
SQL Error: ORA-04091: table COUNTS is mutating, trigger/function may not see it
ORA-06512: at "MV_REFRESH", line 5
ORA-04088: error during execution of trigger 'MV_REFRESH'
04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
*Cause: A trigger (or a user defined plsql function that is referenced in
this statement) attempted to look at (or modify) a table that was
in the middle of being modified by the statement which fired it.
*Action: Rewrite the trigger (or function) so it does not read that table.
答案 0 :(得分:2)
您尝试做的事情似乎并不明智。如果您能解释您尝试解决的业务问题,我们可以帮助您提出更合适的技术实施。
通常,在表的行级触发器中,您无法查询有问题的表。但是,您似乎无需在此触发器中查询表。我的猜测是你只需要使用:new.model_name
。但如果是这样的话,逻辑就没有意义 - 当然,单个属性不可能同时拥有三个不同的值。
IF(:NEW.MODEL_NAME = 'EVENTS' AND
:NEW.MODEL_NAME = 'MARKS' AND
:NEW.MODEL_NAME = 'STAGE')
THEN
REFRESH_MVS();
END IF;
也许你的意思是OR
而不是AND
IF(:NEW.MODEL_NAME = 'EVENTS' OR
:NEW.MODEL_NAME = 'MARKS' OR
:NEW.MODEL_NAME = 'STAGE')
THEN
REFRESH_MVS();
END IF;
可以简化
IF(:NEW.MODEL_NAME IN( 'EVENTS', 'MARKS', 'STAGE') )
THEN
REFRESH_MVS();
END IF;
现在,如果refresh_mvs
尝试查询counts
表,您还将获得变异表异常。如果当前实现尝试查询counts
,则需要将过程更改为接受当前正在插入的行所需的任何数据作为参数。
如果refresh_mvs
实际上是刷新物化视图,则意味着它至少在进行隐式提交。这会产生进一步的问题,因为你不能在触发器中提交(除非触发器被定义为一个在这里不合适的自治事务)。