SQL - 在更新触发器中删除更新的行
Posted
技术标签:
【中文标题】SQL - 在更新触发器中删除更新的行【英文标题】:SQL - Delete updated row in update trigger 【发布时间】:2012-04-02 14:11:06 【问题描述】:我的更新触发器有问题
ALTER TRIGGER tr_MyTable
ON MyTable
AFTER UPDATE
AS
BEGIN TRAN
SET NOCOUNT ON;
If Update(column)
Begin
DELETE FROM MyTable WHERE <condition>
End
SET NOCOUNT OFF
COMMIT TRAN
GO
我正在尝试删除当前已在 MyTable 中更新的行(来自 MayTable)。但是当我运行触发器时,该行没有被删除。是否无法删除当前已在更新触发器中更新的行? (删除和更新在同一张表上)
谢谢!
编辑:
ALTER TRIGGER tr_MyTable
ON MyTable
AFTER UPDATE
AS
BEGIN TRAN
SET NOCOUNT ON;
SELECT @ID = ID
FROM inserted
If Update(column)
Begin
DELETE FROM MyTable WHERE ID = @ID
End
SET NOCOUNT OFF
COMMIT TRAN
GO
编辑 2:
ALTER PROCEDURE sp_Update
(
@ID INTEGER,)
AS
SET NOCOUNT ON
Begin Tran
Update MyTable SET Column = Data where ID = @ID
Commit Tran
SET NOCOUNT OFF
GO
此更新程序正在运行,并且该列已更新。触发器也被触发,并且执行删除(打印语句)之前的行,但不执行删除语句。 但是当我直接在表中更新列时,不形成触发器触发的程序并且删除语句正常工作。我不使用回滚。
【问题讨论】:
你在 SQl 服务器中犯了最严重的触发器错误,即假设只有一条记录将被插入或删除表。如果您执行批量插入,这将不起作用。此代码完全错误,必须更改。 另外,你不应该用 sp_ 开始存储过程,因为这是系统过程使用的。此外,您不应该在没有 try-catch 块的情况下编写事务,以便可以回滚。 【参考方案1】:你是怎么删除的?
您应该从您的 INSERTED 和 DELETED 表中读取您的值,例如:
DELETE FROM MyTable WHERE id in (select ID from INSERTED)
【讨论】:
【参考方案2】:也许您想在 INSTEAD OF 触发器中执行此操作。如果有人尝试更新该列,您可以删除该行,否则您重新执行更新。这里唯一的挑战是您必须在触发器中重新编码更新语句。 (此外,您实际上并不需要在触发器内添加额外的 BEGIN TRAN/COMMIT TRAN。)
CREATE TRIGGER dbo.tr2_myTable
ON dbo.MyTable
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON;
-- update the rows where the column hasn't changed
UPDATE s
SET col1 = i.col1, col2 = i.col2, ...
FROM dbo.MyTable AS s
INNER JOIN inserted AS i
ON s.key = i.key
INNER JOIN deleted AS d
ON i.key = d.key
AND i.column_that_should_not_change = d.column_that_should_not_change;
-- delete the rows where the column HAS changed
-- (note that this requirement sounds odd to me)
DELETE s
FROM dbo.MyTable AS s
INNER JOIN inserted AS i
ON s.key = i.key
INNER JOIN deleted AS d
ON i.key = d.key
AND i.column_that_should_not_change <> d.column_that_should_not_change;
END
GO
请注意,与您的 IF UPDATE()
逻辑不同,此触发器实际上将处理多行(例如,该列已更改的部分,而未更改的部分)。另请注意,即使有人说UPDATE foo SET x = x;
,IF UPDATE(x)
也会为真。
这假设您有一个键列,并且 column_that_should_not_change 不可为空。如果此列允许 NULL,则逻辑会变得更复杂。
【讨论】:
【参考方案3】:有可能。
如果您愿意,您可以在触发器中添加DELETE FROM MyTable
,这应该可以。您是否进行了测试以确认触发器正在执行并且您的代码到达DELETE FROM MyTable WHERE <condition>
行?
【讨论】:
是的,触发器正在执行,并且在执行以上是关于SQL - 在更新触发器中删除更新的行的主要内容,如果未能解决你的问题,请参考以下文章