我们以两个表为例:客户包含客户,产品包含客户购买/使用的产品。
每个产品都通过外键 CustomerID 引用客户,该外键对应于表Customer的主键(它们也具有相同的名称)。
当客户被删除时,所有引用该客户的产品都将被删除: Product.CustomerID 具有 ON DELETE CASCADE 属性。
现在让我们说基地上的客户至少应该有一个产品:
当产品被移除时,如果它是客户的最后一个产品,那么客户也必须被移除。
CREATE OR REPLACE TRIGGER RemoveCustomer
AFTER DELETE ON Product
BEGIN
DELETE FROM Customer
WHERE CustomerID IN (
SELECT c.CustomerID
FROM Customer c
LEFT OUTER JOIN Product p
ON p.CustomerID = c.CustomerID
GROUP BY c.CustomerID HAVING COUNT(p.CustomerID) = 0
);
END;
/
这个解决方案对我来说似乎很自然,但Oracle不喜欢它。 在每个产品的DELETE我得到错误:
ORA-00036: maximum number of recursive SQL levels (50) exceeded
即使DELETE不会导致程序被删除。
令人惊讶的是,这种语法很好用:
CREATE OR REPLACE TRIGGER RemoveCustomer
AFTER DELETE ON Product
BEGIN
FOR my_row IN (
SELECT c.CustomerID
FROM Customer c
LEFT OUTER JOIN Product p
ON p.CustomerID = c.CustomerID
GROUP BY c.CustomerID HAVING COUNT(p.CustomerID) = 0
)
LOOP
DELETE FROM Customer WHERE CustomerID = my_row.CustomerID;
END LOOP;
END;
/
有人可以解释为什么会这样吗?
修改
这里有一个工作示例:
CREATE TABLE Customer (
CustomerID INTEGER PRIMARY KEY
);
CREATE TABLE Product (
ProductID INTEGER PRIMARY KEY,
CustomerID INTEGER,
CONSTRAINT fk_Customer FOREIGN KEY (CustomerID)
REFERENCES Customer
ON DELETE CASCADE
);
INSERT INTo Customer (CustomerID) VALUES (0);
INSERT INTo Customer (CustomerID) VALUES (1);
INSERT INTo Customer (CustomerID) VALUES (2);
INSERT INTo Customer (CustomerID) VALUES (3);
INSERT INTo Customer (CustomerID) VALUES (4);
INSERT INTo Customer (CustomerID) VALUES (5);
INSERT INTo Customer (CustomerID) VALUES (6);
INSERT INTO Product (ProductID, CustomerID) VALUES (0, 0);
INSERT INTO Product (ProductID, CustomerID) VALUES (1, 0);
INSERT INTO Product (ProductID, CustomerID) VALUES (2, 1);
INSERT INTO Product (ProductID, CustomerID) VALUES (3, 2);
INSERT INTO Product (ProductID, CustomerID) VALUES (4, 3);
INSERT INTO Product (ProductID, CustomerID) VALUES (5, 3);
INSERT INTO Product (ProductID, CustomerID) VALUES (6, 3);
INSERT INTO Product (ProductID, CustomerID) VALUES (7, 4);
INSERT INTO Product (ProductID, CustomerID) VALUES (8, 5);
INSERT INTO Product (ProductID, CustomerID) VALUES (9, 5);
INSERT INTO Product (ProductID, CustomerID) VALUES (10, 6);
CREATE OR REPLACE TRIGGER RemoveCustomer
AFTER DELETE ON Product
BEGIN
DELETE FROM Customer
WHERE CustomerID IN (
SELECT c.CustomerID
FROM Customer c
LEFT OUTER JOIN Product p
ON p.CustomerID = c.CustomerID
GROUP BY c.CustomerID HAVING COUNT(p.CustomerID) = 0
);
END;
/
/* This request will produce the error */
DELETE FROM Product WHERE CustomerID = 3;
答案 0 :(得分:2)
令人惊讶的是,在products
上执行删除后,似乎customers
上的级联删除声明始终 - 即使没有客户被删除也是如此。例如:
SQL> delete customer where customerid = 9999999;
delete customer where customerid = 9999999
*
ERROR at line 1:
ORA-00036: maximum number of recursive SQL levels (50) exceeded
ORA-06512: at "TTEST.REMOVECUSTOMER", line 2
...
使用第二个版本的触发器,当没有没有产品的客户时,永远不会执行for
循环体,因此永远不会发生customers
的删除,并且避免无限循环。 / p>