0

可能重复:
为什么这个触发器会失败?它说无效的标识符。

CREATE MATERIALIZED VIEW ORDERS_MV

BUILD IMMEDIATE

REFRESH COMPLETE ON DEMAND AS

SELECT * FROM ORDERS;

CREATE OR REPLACE TRIGGER update_ship_receive

INSTEAD OF INSERT ON ORDERS_MV

FOR EACH ROW

BEGIN

  UPDATE ORDERS SET EXPECTED_SHIP_DATE = ORDER_DATE+5;

  UPDATE ORDERS SET EXPECTED_RECEIVE_DATE = SHIP_DATE+1 
WHERE SHIPPING_METHOD = '1 DAY';

  UPDATE ORDERS SET EXPECTED_RECEIVE_DATE = SHIP_DATE+2
 WHERE SHIPPING_METHOD = '2 DAY';

  UPDATE ORDERS SET EXPECTED_RECEIVE_DATE = SHIP_DATE+5 
WHERE SHIPPING_METHOD = 'GROUND';

END;
/
4

2 回答 2

4

这不起作用,因为物化视图不是视图,它是一种特殊的表:它有数据,我们可以用它强制约束,等等。

因此,让我们看看你的底层流程逻辑,这是令人困惑的。您有一个基于表格的物化视图。现在,您想要构建一个触发器,该触发器在将行插入物化视图时 更新基表。

  1. 您是否希望物化视图包含更改的数据?

  2. 由于您指定 SQL 的方式,触发器(如果它可以工作)将更新 ORDERS 表中的每一行。

  3. 因为触发器是 FOR EACH ROW 刷新,所以物化视图将多次更新整个 ORDERS 表,ORDERS 表中的每一行更新一次。

  4. INSTEAD OF 触发器执行触发器主体中的代码,而不是(而不是)触发器标头中指定的操作。因此(如果它可以工作)触发器将更新 ORDERS 表并且不向实体化视图中插入任何行。

所以我希望你能看到这个错误正在阻止你犯更严重的架构错误。您需要做的是澄清您的业务流程,然后寻求用 SQL 来表达它。在我看来,最合适的解决方案是 ORDERS 表上的 BEFORE UPDATE 触发器。像这样的东西:

CREATE OR REPLACE TRIGGER update_ship_receive
    BEFORE INSERT or UPDATE ON ORDERS
    FOR EACH ROW
BEGIN

    if :new.EXPECTED_SHIP_DATE is null
    then
        :new.EXPECTED_SHIP_DATE = :new.ORDER_DATE+5;
    end if;

    if :new.EXPECTED_RECEIVE_DATE is null
    then 
        case :new.SHIPPING_METHOD
            when '1 DAY' then        
               :new.EXPECTED_RECEIVE_DATE = :new.SHIP_DATE+1; 
            when '2 DAY' then        
               :new.EXPECTED_RECEIVE_DATE = :new.SHIP_DATE+2;
            when 'GROUND' then        
               :new.EXPECTED_RECEIVE_DATE = :new.SHIP_DATE+5; 
            else
               null;
         end case;
    end if;
END;
/

然后,您只有一个简单的物化视图,当您刷新它时无需进行任何相关处理。显然,您的实际业务逻辑可能会决定不同的解决方案。

于 2011-03-04T07:34:51.907 回答
1

物化视图不是常规视图。它有一个与之相关的数据段。

于 2011-03-04T06:30:42.127 回答