【问题标题】:create trigger on INSERT IN table for specific values在 INSERT IN 表上为特定值创建触发器
【发布时间】:2014-04-23 01:56:20
【问题描述】:

我正在尝试在 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.

【问题讨论】:

    标签: oracle triggers insert


    【解决方案1】:

    看来您正在尝试做的事情并不明智。如果您能解释您要解决的业务问题,我们或许可以帮助您提出更合适的技术实施方案。

    通常,在表的行级触发器中,您无法查询相关表。不过,您似乎不需要在此触发器中查询表。我的猜测是你只需要使用: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 实际上是在刷新物化视图,这意味着它至少在进行隐式提交。这将产生更多问题,因为您无法在触发器中提交(除非触发器被定义为不适合此处的自治事务)。

    【讨论】:

    • 我要做的就是在所有 3 个表都完成刷新并出现在 COUNTS 表中以运行 REFRESH_MVS() 过程。也许这不是要走的路?
    • @Angelina - “在所有 3 个表都完成刷新之后”是什么意思?您是否有某种 ETL 过程正在加载 eventsmarksstage 表?如果是这样,为什么该过程不启动物化视图的刷新?如果这些是通过dbms_scheduler 安排的单独作业,您可以创建作业以刷新物化视图并将其添加为在这三个链步骤完成时运行的链中的一个步骤。或者您可以有一个单独的作业定期运行,查询counts 表,并刷新物化视图。
    • 我的问题是独立脚本。每个表都有自己的脚本来加载该表,然后插入 table_name、count、start_dt、end_dt。所以我找不到检查所有 3 张桌子何时完全完成的方法。
    • @Angelina - 大概,每个脚本都是以某种方式安排的。那是什么机制。如果您使用dbms_scheduler,您可以创建取决于多个先前步骤的成功完成的步骤。或者您可以编写一个定期运行的单独作业,查询counts 表,并调用您的存储过程。
    • @Angelina - 如果使用dbms_scheduler,那么,是的,将其构建为具有多个依赖项的链中的步骤是有意义的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    • 2021-11-24
    • 1970-01-01
    • 2023-03-20
    相关资源
    最近更新 更多