使用触发器实现引用完整性操作(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

细分:

  1. inner joindeleted table 将确保您只删除 OrderNumber 与已删除的记录相同的记录 来自 order_item table.
  2. 的记录
  3. left joinorder_item table 以及 where 子句确保您只删除 订单 table 如果他们没有附加 order_item 记录。

您的语法看起来更像 Oracle; SQL 服务器语法完全不同。例如,没有 new:old:。相反,有表格 inserteddeleted

如果我没理解错的话,您想从删除语句中的订单中删除一项。然后,如果最后一项已被删除,您想要删除订单本身。我认为以下是这样做的:

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;