【问题标题】:How can I implement a SQL Server trigger as an alternative to ON DELETE CASCADE?如何实现 SQL Server 触发器作为 ON DELETE CASCADE 的替代方法?
【发布时间】:2017-01-15 22:49:33
【问题描述】:

我想在 SQL Server 2016 中使用时态表。目前时态表不允许使用 ON DELETE CASCADE。如何实现触发器来模仿行为?我想保留外键,因为我在我的应用程序中使用实体框架的导航属性。

我认为后触发器不起作用,因为删除语句不适用于外键条件。

假设我们有以下简单的情况:

  1. UserRole.UserId:User.Id 的外键
  2. UserRole.RoleId:Role.Id 的外键

如果我删除 Id == 2 的角色,而不是删除 UserRole 中的第二行和第四行。在时态表中没有 ON DELETE CASCADE 的情况下如何实现这一点?

【问题讨论】:

  • 你听说过Instead of Triggers吗,google一下吧。
  • 是的,但是在当前表或历史表上都不允许使用 INSTEAD OF 触发器,以避免使 DML 逻辑无效。 AFTER 触发器只允许在当前表上。它们在历史表中被阻止以避免使 DML 逻辑失效。
  • 考虑一下 - 如果通过类似触发器的方式实现ON DELETE CASCADE 是微不足道的,为什么微软开发人员不使用这种机制实现ON DELETE CASCADE,而不是将其列为限制?您尝试的任何解决方法都可能遇到类似的限制。
  • 我在应用端解决了这个问题。所以我扩展了 EntityTypeConfiguration 并使用反射来触发删除语句的正确顺序。

标签: sql-server triggers sql-server-2016


【解决方案1】:

就像我在 cmets 部分中提到的,您将需要一个Instead of Trigger,类似这样......

CREATE TRIGGER tr_CascadeDelete_UserRole
ON [Role]
INSTEAD OF DELETE
AS
BEGIN
  SET NOCOUNT ON;

  --** Delete Rows from [UserRole] table first 
  DELETE FROM [UserRole]
  WHERE EXISTS (SELECT 1 
                FROM Deleted d
                WHERE d.RoleID = [UserRole].RoleID)

  --** Delete Rows from [Role] table first 
  DELETE FROM [Role]
  WHERE EXISTS (SELECT 1 
                FROM Deleted d
                WHERE d.RoleID = [Role].RoleID)

END

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
相关资源
最近更新 更多