基于订单行的Oracle触发器更新实现了如何避免突变错误

时间:2012-04-28 14:09:00

标签: sql oracle triggers event-triggers

对于典型的产品和发货数据库我正在探索运行触发器的最佳方式:

  1. 当订单行设置为“完成”时,会运行以下触发器:
  2. 查找该订单的任何其他订单行。
  3. 如果该订单的所有其他订单行也是“完整”
  4. 更新订单标题表格以完成。
  5. 对于clatiry:订单表头将存储整体oder总数,orderLines表存储订单的每个产品。

    到目前为止,触发器是这样写的:

    CREATE OR REPLACE TRIGGER orderComplete
    after update ON orderline
    for each row
    WHEN (new.orderline_fulfilled = 'Y')
    DECLARE count NUMBER := 5;
    ordersNotDone NUMBER;
    BEGIN
    
    SELECT COUNT(Orderline_fulfilled) INTO ordersNotDone
    FROM orderHeader
    JOIN orderline ON
    orderHeader.Order_id = orderLine.Orderline_order
    WHERE Order_id = :old.orderline_order
    AND orderline_fulfilled = 'Y';
    
    IF ordersNotDone = 0
    THEN
    UPDATE orderHeader
    SET completed = SYSDATE
        WHERE orderId = :old.orderline_order;
    ENDIF;
    
    END;
    

    当更新订单行时,上述内容会导致突变错误。

3 个答案:

答案 0 :(得分:3)

使用触发器实现完整性本身就存在问题,因为RDBMS读取一致性模式允许同时进行多次更改,无法看到彼此的结果。

更好的解决方案可能是避免对数据进行非规范化,并依赖于检测是否存在不完整的订单行来识别不完整的订单。由于这是少数情况,因此可以使用基于函数的索引对其进行优化:

create index my_index on orderline(case orderline_complete when 'NO' then orderid else null end)

这将仅对orderline_complete为“NO”的订单行的值进行索引,因此如果表中只有100个这样的行,那么索引将只包含100个条目。

识别不完整的订单只是对具有查询的非常紧凑的索引的完整或快速完整索引扫描的问题:

select distinct
  case orderline_complete when 'NO' then orderid else null end orderid
from
  orderline
where
  case orderline_complete when 'NO' then orderid else null end is not null;

答案 1 :(得分:0)

最简单的答案是使用稍微不同类型的触发器,该触发器不会在更新行之后但在更新表之后触发。这不会遇到这个问题。

做类似的事情:

CREATE or REPLACE TRIGGER trigger_name
AFTER INSERT ON orderline --note no for each row
BEGIN

  --loop over all orders which contain no unfulfilled orders
  FOR lrec IN (SELECT order_id FROM orderline group by order_id where not exists (select 1 from orderline where orderline_fulfilled = 'Y'))
  LOOP
    -- do stuff to order id because this are complete
  END LOOP;
END;

所以在这里我们可能已经在插入上完成了多个订单,因此触发器需要应对此问题。对不起,我家里没有oracle实例。希望这有帮助

答案 2 :(得分:0)

如果您使用的是11g,请检查复合触发器,例如:http://www.toadworld.com/KNOWLEDGE/KnowledgeXpertforOracle/tabid/648/TopicID/TRGC1/Default.aspx