好的,我有两个表 - ORDERS 和 ORDERLINES - 它们具有基本相同的问题,每个表都有触发器来解决问题。问题是除了具有表级唯一性的 PK 之外,在一个名为 RECID 的字段上,还有另一个字段 RECNO,它需要与另一个字段的关系是唯一的。
这些表与 FK 相关,如下所示:
ORDERS.WAREHOUSEID > WAREHOUSES.CUSTOMERID > CUSTOMERS
和
ORDERSLINES.ORDERID > ORDERS
OnORDERS
并且ORDERSLINES
我有BEFORE INSERT
触发器来分配特定于领域的唯一RECNO。
在ORDERS
中,RECNO需要在记录范围内是唯一的CUSTOMERS
。
在ORDERLINES
中,RECNO需要在记录范围内是唯一的ORDERS
。
触发器ORDERS
工作得很好。插入新订单时,会为其所属的客户 分配下一个唯一的RECNO 。
ORDERLINES
另一方面,应该在它所属的顺序内分配下一个唯一RECNO的触发器会抛出可怕的{ORA-04091: table ORDERLINES is mutating, trigger/function may not see it}异常。
这是有效的触发器:
CREATE OR REPLACE TRIGGER ORDERS_BI
BEFORE INSERT ON ORDERS
FOR EACH ROW
DECLARE
CUSTID WAREHOUSES.CUSTOMERID%TYPE;
BEGIN
SELECT MIN(CUSTOMERID) INTO CUSTID FROM WAREHOUSES
WHERE NVL(WARE_ID, '-') = NVL(:NEW.WAREHOUSEID, '-');
SELECT NVL(MAX(RECNO), 0) + 1
INTO :NEW.RECNO
FROM deploy.ORDERS O
LEFT JOIN deploy.WAREHOUSES W
ON NVL(W.REC, '-') = NVL(O.WAREHOUSEID, '-')
WHERE NVL(W.CUSTOMERID, '-') = NVL(CUSTID, '-');
END;
这是不起作用的触发器:
CREATE OR REPLACE TRIGGER ORDERLINES_BI
BEFORE INSERT ON ORDERLINES
FOR EACH ROW
DECLARE
nORDERID ORDERLINES.ORDERID%TYPE;
BEGIN
SELECT MIN(ORDERID) INTO nORDERID FROM REVORDERS
WHERE ORDERID = :NEW.ORDERID;
SELECT NVL(MAX(RECNO), 0) + 1
INTO :NEW.RECNO
FROM deploy.ORDERLINES L
LEFT JOIN deploy.ORDERS O
ON O.ORDERID = L.ORDERID
WHERE O.ORDERID = nORDERID;
END;
有人可以解释为什么第一个有效,而第二个无效?有什么方法可以重写第二个以使其工作吗?