【问题标题】:pl/sql statement Triggerpl/sql语句触发器
【发布时间】:2021-02-25 06:26:42
【问题描述】:

假设我们有以下两个表:

OrderHeader(OrderID, Odate, CustID, Total)

Order_Item(OrderID,ItemID, Qty, Subtotal)

编写一个语句级触发器,将 orderHeader 表中的 Total 更新为 每当插入、更新或删除事件时 order_item 记录的总值 发生在 order_item 表上。对于任何更新错误,引发异常。

到目前为止,我已经写了这个:

create or replace TRIGGER SECURE_ORDER
AFTER INSERT OR DELETE OR UPDATE ON Order_Item
declare
 sum1 Number;
BEGIN
SELECT SUM(Qty*Price) Into sum1 FROM Order_Item Inner join Item Using(ItemID) WHERE OrderID=:OLD.OrderID;
UPDATE OrderHeader set Total=sum1 where OrderID=:OLD.OrderID;
EXCEPTION
    WHEN too_many_rows then
        dbms_output.put_line('Too many rows');
    WHEN no_data_found then
        dbms_output.put_line('No Data Found');
    WHEN others then
        dbms_output.put_line('other error');
END;

但这是不正确的,因为问题声明说我必须编写一个语句级触发器,它不会让我访问 NEW 和 OLD 关键字。我不知道如何在语句级触发器中执行此操作。任何帮助将不胜感激。

【问题讨论】:

  • "对于任何更新错误,引发异常。"请edit您的问题提供异常的全部详细信息?

标签: oracle plsql triggers


【解决方案1】:

您可以只使用一个MERGE 语句:

CREATE TRIGGER SECURE_ORDER
AFTER INSERT OR DELETE OR UPDATE ON Order_Item
BEGIN
  MERGE INTO OrderHeader dst
  USING (
    SELECT COALESCE( oh.OrderID, o.OrderID ) AS OrderID,
           COALESCE( SUM( o.Qty*i.Price ), 0 ) AS total
    FROM   OrderHeader oh
           FULL OUTER JOIN Order_Item o
           ON oh.OrderID = o.OrderID
           LEFT OUTER JOIN Item i
           ON ( o.ItemID = i.ItemID )
    GROUP BY COALESCE( oh.OrderID, o.OrderID )
  ) src
  ON ( src.OrderID = dst.OrderID )
  WHEN MATCHED THEN
    UPDATE SET total = src.total
  WHEN NOT MATCHED THEN
    INSERT ( OrderID, Total ) VALUES ( src.OrderID, src.Total );
END;
/

那么,如果你有桌子:

CREATE TABLE Item (
  ItemID NUMBER(10,0)
         GENERATED ALWAYS AS IDENTITY
         CONSTRAINT Item__ItemID__PK PRIMARY KEY,
  Name   VARCHAR2(20)
         NOT NULL,
  Price  NUMBER(12,2)
         NOT NULL
         CONSTRAINT Item__Price_GTE_0__CHK CHECK ( Price >= 0 )
);

CREATE TABLE Order_Item (
  OrderID INT
          -- CONSTRAINT Order_Item__OrderID__FK REFERENCES Orders ( OrderID )
          NOT NULL,
  Qty     INT
          NOT NULL
          CONSTRAINT Order_Item__Qty_GT_0__CHK CHECK ( Qty > 0 ),
  ItemID  INT
          NOT NULL
          CONSTRAINT Order_Item__ItemID__FK REFERENCES Item ( ItemId ),
  CONSTRAINT Order_Item__OID__IID__PK PRIMARY KEY ( OrderID, ItemID )
);

CREATE TABLE OrderHeader (
  OrderID INT
          NOT NULL,
  total   NUMBER(14,2)
          NOT NULL
);

如果你:

INSERT INTO Item ( Name, Price ) VALUES ( 'Item 001', 1.00 );
INSERT INTO Item ( Name, Price ) VALUES ( 'Item 002', 2.00 );
INSERT INTO Item ( Name, Price ) VALUES ( 'Item 003', 2.50 );
INSERT INTO Order_Item ( OrderID, ItemID, Qty ) VALUES ( 1, 1, 3 );
INSERT INTO Order_Item ( OrderID, ItemID, Qty ) VALUES ( 1, 2, 1 );
INSERT INTO Order_Item ( OrderID, ItemID, Qty ) VALUES ( 1, 3, 2 );

OrderHeader 表包含:

SELECT * FROM OrderHeader;
订单号 |全部的 ------: | ----: 1 | 10

如果你这样做:

UPDATE Order_Item
SET   Qty     = 8
WHERE OrderID = 1
AND   ItemID  = 1;

OrderHeader 表包含:

SELECT * FROM OrderHeader;
订单号 |全部的 ------: | ----: 1 | 15

如果你这样做:

DELETE FROM Order_Item
WHERE  ( OrderID, ItemID ) IN ( (1,2), (1,3) );

OrderHeader 表包含:

SELECT * FROM OrderHeader;
订单号 |全部的 ------: | ----: 1 | 8

最后,如果你这样做了:

DELETE FROM Order_Item;

OrderHeader 表包含:

SELECT * FROM OrderHeader;
订单号 |全部的 ------: | ----: 1 | 0

db小提琴here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 2011-08-06
    相关资源
    最近更新 更多