使用触发器实现引用完整性操作(SQL 服务器)
Using triggers to implement referential integrity actions (SQL Server)
我正在尝试为我的表实施一些触发器
2 个表是 ORDERS
(有订单)和 ORDERS_ITEMS
(每个订单都有项目),我想在没有更多时删除 ORDER
ITEMS
在那 ORDER
.
我希望我的触发器看起来像这样
CREATE TRIGGER DELETE_ORDER_WHEN_NO_ITEMS
INSTEAD OF DELETE
ON ORDER
DECLARE rowcount int;
BEGIN
// First detemine if this is the last item in the ORDER
SELECT Count(*)
INTO rowcount
FROM ORDER_ITEM
WHERE ORDER_ITEM.ItemNumber = old:ItemNumber;
// Delete ITEM row
DELETE ORDER_ITEM
WHERE ORDER_ITEM.ItemNumber = old:ItemNumber;
// Last ITEM in ORDER delete the whole ORDER
IF (rowcount = 1) THEN
DELETE ORDER
WHERE ORDER.OrderNumber = old:OrderNumber;
END IF
END;
我不确定如何在 SQL 服务器上写这个,我从一本书上得到了算法,但我不能 运行 它在 SQL 服务器上。
不要为此使用触发器。使用外键 cascade delete.
更新
抱歉,我跳错了结论。如果你想在没有项目连接的情况下删除订单,级联删除将无济于事。
在 order_item table 上使用 after delete 触发器并在此处写入此删除语句:(再次更新)
CREATE TRIGGER order_item_delete ON order_item
FOR DELETE
AS
DELETE order
FROM order
INNER JOIN deleted ON (order.OrderNumber = deleted.OrderNumber) -- 1
LEFT JOIN order_Item ON(order.OrderNumber = order_item.OrderNumber)
WHERE order_Item.ItemNumber IS NULL -- 2
GO
细分:
inner join
和 deleted
table 将确保您只删除 OrderNumber 与已删除的记录相同的记录
来自 order_item table. 的记录
-
left join
和 order_item table 以及 where
子句确保您只删除 订单 table 如果他们没有附加 order_item 记录。
您的语法看起来更像 Oracle; SQL 服务器语法完全不同。例如,没有 new:
和 old:
。相反,有表格 inserted
和 deleted
。
如果我没理解错的话,您想从删除语句中的订单中删除一项。然后,如果最后一项已被删除,您想要删除订单本身。我认为以下是这样做的:
CREATE TRIGGER trg_orders_delete_one_item ON orders
INSTEAD OF DELETE
AS
begin
with todelete as (
select oi.*, row_number() over (partition by OrderId order by ItemNumber desc) as seqnum
from Order_Items oi
where oi.OrderId in (select OrderId from deleted)
)
delete todelete
where seqnum = 1;
with todelete as (
select o.*
from orders o
where o.OrderId in (select OrderId from deleted)
)
delete todelete
where not exists (select 1
from order_item oi
where oi.OrderId = todelete.OrderId
)
end;
我正在尝试为我的表实施一些触发器
2 个表是 ORDERS
(有订单)和 ORDERS_ITEMS
(每个订单都有项目),我想在没有更多时删除 ORDER
ITEMS
在那 ORDER
.
我希望我的触发器看起来像这样
CREATE TRIGGER DELETE_ORDER_WHEN_NO_ITEMS
INSTEAD OF DELETE
ON ORDER
DECLARE rowcount int;
BEGIN
// First detemine if this is the last item in the ORDER
SELECT Count(*)
INTO rowcount
FROM ORDER_ITEM
WHERE ORDER_ITEM.ItemNumber = old:ItemNumber;
// Delete ITEM row
DELETE ORDER_ITEM
WHERE ORDER_ITEM.ItemNumber = old:ItemNumber;
// Last ITEM in ORDER delete the whole ORDER
IF (rowcount = 1) THEN
DELETE ORDER
WHERE ORDER.OrderNumber = old:OrderNumber;
END IF
END;
我不确定如何在 SQL 服务器上写这个,我从一本书上得到了算法,但我不能 运行 它在 SQL 服务器上。
不要为此使用触发器。使用外键 cascade delete.
更新
抱歉,我跳错了结论。如果你想在没有项目连接的情况下删除订单,级联删除将无济于事。
在 order_item table 上使用 after delete 触发器并在此处写入此删除语句:(再次更新)
CREATE TRIGGER order_item_delete ON order_item
FOR DELETE
AS
DELETE order
FROM order
INNER JOIN deleted ON (order.OrderNumber = deleted.OrderNumber) -- 1
LEFT JOIN order_Item ON(order.OrderNumber = order_item.OrderNumber)
WHERE order_Item.ItemNumber IS NULL -- 2
GO
细分:
inner join
和deleted
table 将确保您只删除 OrderNumber 与已删除的记录相同的记录 来自 order_item table. 的记录
-
left join
和 order_item table 以及where
子句确保您只删除 订单 table 如果他们没有附加 order_item 记录。
您的语法看起来更像 Oracle; SQL 服务器语法完全不同。例如,没有 new:
和 old:
。相反,有表格 inserted
和 deleted
。
如果我没理解错的话,您想从删除语句中的订单中删除一项。然后,如果最后一项已被删除,您想要删除订单本身。我认为以下是这样做的:
CREATE TRIGGER trg_orders_delete_one_item ON orders
INSTEAD OF DELETE
AS
begin
with todelete as (
select oi.*, row_number() over (partition by OrderId order by ItemNumber desc) as seqnum
from Order_Items oi
where oi.OrderId in (select OrderId from deleted)
)
delete todelete
where seqnum = 1;
with todelete as (
select o.*
from orders o
where o.OrderId in (select OrderId from deleted)
)
delete todelete
where not exists (select 1
from order_item oi
where oi.OrderId = todelete.OrderId
)
end;