对于删除触发器不起作用(Microsoft SQL Server Management Studio)

时间:2012-05-02 09:58:26

标签: sql sql-server-2008 triggers sql-delete

我有一张桌子大学和一张桌子城市。它们之间存在m:n关系,因此关系将保存在另一个名为CityUniversities的表中。现在我想编写一个触发器,删除大学中删除大学时城市和大学之间的所有关系。然而,它不起作用。尝试删除大学时,我总是收到以下错误消息:

“Msg 547,Level 16,State 0,Line 2 DELETE语句与REFERENCE约束“FK_CityUniversities_Universities”冲突。冲突发生在数据库“Alumni_Dev”,表“dbo.CityUniversities”,列“UniversityId”中。 声明已经终止。“

这是我已经实施并成功执行的触发器(对于表大学):

USE [Alumni_Dev]
GO
/****** Object:  Trigger [dbo].[deleteUni]    Script Date: 05/02/2012 11:42:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[deleteUni]
ON  [dbo].[Universities] 
FOR DELETE
AS 
DECLARE @UniId int
SELECT @UniId = (SELECT UniversityId FROM deleted)
BEGIN
--Remove constraints
DELETE FROM dbo.CityUniversities WHERE UniversityId = @UniId;
END  

我已经将我的解决方案与几个参考文献进行了比较,但是我找不到任何可能出错的内容。可能是其中一个受影响的表中有任何错误的设置吗?

我很高兴听到任何建议。


我终于通过以下触发器解决了我的问题(对Nikola来说):

ALTER TRIGGER [dbo].[deleteUni]
ON  [dbo].[Universities] 
INSTEAD OF DELETE
AS 
DECLARE @UniId int
SELECT @UniId = UniversityId FROM deleted
BEGIN
--Remove constraints
DELETE FROM dbo.CityUniversities WHERE UniversityId = @UniId;
DELETE FROM dbo.Universities WHERE UniversityId = @UniId;
END

1 个答案:

答案 0 :(得分:4)

触发器不能用于从其他表中删除孤立记录,因为在执行触发器之前会检查约束。您应该设置ON DELETE CASCADE

如果您想在删除前执行某些检查,也可以使用INSTEAD OF触发器,但不要忘记在触发器末尾添加delete Universities where ...以实际删除记录。

关于触发器的两点:

  • 在触发器主体的开头添加SET NOCOUNT ON以避免触发器内部的sql语句的可能性更改"受影响的行的值#34;调用代码时可能需要的,
  • 不要将已删除和已插入的表视为仅包含一个记录。当你试图删除两所大学时会有令人讨厌的惊喜。您应该将使用的表与已删除或插入的表连接起来,将它们用作过滤器,或者使用exists:

    delete dbo.CityUniversities
      from dbo.CityUniversities
     inner join deleted
        on dbo.CityUniversities.UniversityId = deleted.UniversityId 
    

delete dbo.CityUniversities
 where exists (select null
                 from deleted
                where deleted.UniversityId =dbo.CityUniversities.UniversityId)

哦,

SELECT @UniId = (SELECT UniversityId FROM deleted)

相当于:

SELECT @UniId = UniversityId FROM deleted