简体   繁体   English

使用触发器来实现引用完整性操作(SQL Server)

[英]Using triggers to implement referential integrity actions (SQL Server)

I'm trying to implement some triggers for my tables 我正在尝试为我的桌子实施一些触发器

2 of the tables are ORDERS (has orders) and ORDERS_ITEMS (has items for each order), and I want to delete the ORDER when there are no more ITEMS in that ORDER . 表中的2个是ORDERS (有订单)和ORDERS_ITEMS (每个订单都有项目),并且当该ORDER中没有更多ITEMS时,我想删除该ORDER

I want my trigger to look something like this 我希望我的扳机看起来像这样

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;

I'm not sure how to write this in SQL Server and I had the algorithm from a book but I couldn't run it on SQL Server. 我不确定如何在SQL Server中编写此代码,并且从书中获得了算法,但是无法在SQL Server上运行它。

Don't use a trigger for that. 不要为此使用触发器。 Use foriegn key with cascade delete. 将foriegn键与级联删除一起使用。

Update 更新

Sorry, I've jumped to the wrong conclution. 抱歉,我跳错了答案。 If you want to delete the orders when there are no items connected to it, cascade delete will not help. 如果要在没有任何项目连接时删除订单,则级联删除将无济于事。
Use a triger for after delete on the order_item table and write this delete statement there: ( updated again ) 在order_item表上删除后使用触发器进行触发,并在该表中写入以下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

Breakdown: 分解:

  1. The inner join with deleted table will ensures you only delete records where the OrderNumber is the same as the deleted records from order_item table. inner join表与deleted表的连接将确保您仅删除OrderNumberorder_item表中已删除记录相同的记录。
  2. The left join with order_item table along with the where clause ensures you only delete records from orders table if they have no order_item records attached to them. order_item表的left join以及where子句可确保您仅在订单未附加order_item记录的情况下从订单表中删除记录。

Your syntax looks more like Oracle; 您的语法看起来更像Oracle。 SQL Server syntax is quite different. SQL Server语法完全不同。 For instance, there is no new: and old: . 例如,没有new:old: Instead, there are tables, inserted and deleted . 而是有inserteddeleted表。

If I understand correctly, you want to remove one item from the orders in the delete statement. 如果我理解正确,则想从delete语句的订单中删除一项。 Then, if the last item has been removed, you want to delete the order itself. 然后,如果最后一个项目已被删除,则要删除订单本身。 I think the following does this: 我认为以下是这样做的:

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM