删除后使用SQL触发器以使用多行删除

时间:2011-08-12 03:51:23

标签: sql-server triggers

我有一个带有“订单”列的表,需要维护一系列连续的唯一数字。我正在尝试创建的是一个触发器,它在删除更新“order”列的行后触发,以便数字保持连续。

我知道很多人都认为“订单”列只需要连续,而不是连续,但是有很多前端JavaScript和其他SQL,用于订购/重新排序这些依赖于订单的项目连续的。我宁愿简单地让这个触发器工作而不是重写,当然我愿意接受建议;)

对于单行删除,我的触发器工作正常,但是当发生多行删除时,只有第一行被删除而其余行保持没有错误抛出。

我认为问题可能是递归,因为它更新了它触发的表,但它只是一个删除触发器所以我不认为这是问题所在。关闭RECURSIVE_TRIGGERS并没有解决问题。

以下是代码:

CREATE TABLE [dbo].[Item]
(
[ItemID] INT NOT NULL IDENTITY(1, 1),
[ItemOrder] INT NOT NULL,
[ItemName] NVARCHAR (50)  NOT NULL
)
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

CREATE TRIGGER [dbo].[trItem_odr] ON [dbo].[Item]
    AFTER DELETE
AS
    BEGIN
        SET NOCOUNT ON ;

        DECLARE @MinOrder INT

        SELECT  @MinOrder = MIN(ItemOrder)
        FROM    DELETED

        DECLARE @UpdatedItems TABLE
            (
             ID INT IDENTITY(0, 1)
                    PRIMARY KEY,
             ItemID INT
            )

        INSERT  INTO @UpdatedItems (ItemID)
                SELECT  ItemID
                FROM    dbo.Item
                WHERE   ItemOrder > @MinOrder
                        AND ItemID NOT IN (SELECT   ItemID
                                           FROM     DELETED)
                ORDER BY ItemOrder


        UPDATE  dbo.Item
        SET     ItemOrder = (SELECT ID + @MinOrder
                             FROM   @UpdatedItems
                             WHERE  ItemID = Item.ItemID)
        WHERE   ItemID IN (SELECT   ItemID
                           FROM     @UpdatedItems)

    END
GO

ALTER TABLE [dbo].[Item] ADD CONSTRAINT [PK_Item] PRIMARY KEY CLUSTERED  ([ItemID])
GO
ALTER TABLE [dbo].[Item] ADD CONSTRAINT [IX_Item_1] UNIQUE NONCLUSTERED  ([ItemName])
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_Item_2] ON [dbo].[Item] ([ItemOrder])
GO

INSERT INTO [dbo].[Item] ([ItemOrder], [ItemName])
SELECT 1, N'King Size Bed' UNION ALL
SELECT 2, N'Queen size bed' UNION ALL
SELECT 3, N'Double Bed' UNION ALL
SELECT 4, N'Single Bed' UNION ALL
SELECT 5, N'Filing Cabinet' UNION ALL
SELECT 6, N'Washing Machine' UNION ALL
SELECT 7, N'2 Seater Couch' UNION ALL
SELECT 8, N'3 Seater Couch' UNION ALL
SELECT 9, N'1 Seater Couch' UNION ALL
SELECT 10, N'Flat Screen TV' UNION ALL
SELECT 11, N'Fridge' UNION ALL
SELECT 12, N'Dishwasher' UNION ALL
SELECT 13, N'4 Seater couch' UNION ALL
SELECT 14, N'Lawn Mower' UNION ALL
SELECT 15, N'Dining table'
GO

1 个答案:

答案 0 :(得分:3)

重写你的前端。 希望以更少的运行时间交换更多的开发时间

通过更新表中的所有无序行保持订单列连续是非常低效的(删除第1项=>更新100000000项)导致潜在的巨大更新操作,因为更新修改会产生巨大的争用行的很多,因此几乎所有读取都满足,最终在并发下不正确(最终会出现间隙和重叠 )。不要这样做。

相关问题