【问题标题】:Don't Understand Sql Server Error不了解 Sql Server 错误
【发布时间】:2011-01-12 12:27:37
【问题描述】:

我有一个用户表(User),需要创建一个新表来跟踪哪些用户推荐了其他用户。所以,基本上,我在同一个表中的行之间创建了一个多对多的关系。

所以我正在尝试使用列 UserId 和 UserReferredId 创建表 UserReferrals。我将两列都设为复合主键。并且这两列都是链接到 User.UserID 的外键。

由于删除用户也应该删除关系,因此我将两个外键都设置为级联删除。删除用户后,UserReferrals 中的所有相关行也应删除。

但这给了我信息:

'User' table saved successfully 'UserReferrals' table Unable to create relationship 'FK_UserReferrals_User'. Introducing FOREIGN KEY constraint 'FK_UserReferrals_User' on table 'UserReferrals' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint. See previous errors.

我没有收到此错误。级联删除只会删除带有外键的行,对吗?那么怎么会导致“循环级联路径”呢?

感谢任何提示。

【问题讨论】:

  • 你确定你没有不小心向后设置外键约束之一吗?
  • 我刚刚再次检查了良好的措施。两列都将 User 表显示为主键表,将 UserReferrals 显示为外键表。

标签: sql-server relational-database cascading-deletes


【解决方案1】:

如果表 (A) 上的 FK 引用了表 (B),而表 (B) 又与 (A) 有关系,或者 FK 引用同一表中的 PK,则可能会引入以下情况:它循环。有时这在逻辑上是不可能的——但在纯理论上,在 SQL 引擎看来是可能的。

这是无法避免的。通常我们在 SP 中处理这些(在 EF 中我们可以映射到 delete 方法)。

【讨论】:

  • 能否请您详细说明外键如何循环?只有 FK 侧级联,对吧?那么它怎么会导致关系的 PK 方面的级联呢?
  • 您的 [User] 表通过与 [UserReferals] 的关系引用了自身并再次返回。因此,用户 A 可能会“推荐”用户 B,而用户 B 可能会推荐用户 A,这会导致循环级联场景。我所说的“关系的 PK 端”是指当 PK 也是约束的目标或表引用自身时。
  • 对不起,如果我没有得到它,但两列都在关系的 FK 方面。因此,任何级联都将在 UserReferrals 表处结束。也就是说,删除不会从关系的 FK 端级联,因为它们只会从关系的 PK 端级联。你能看出我的想法哪里出了问题吗?
  • 假设 [Id] 是用户的 PK 并且 UserReferrals 具有 UserId 和 ReferredUserId 作为 FK,来自用户的级联具有到 UserReferrals 的多个路径(每列一个)。我同意在您的实例中,这在逻辑上是不相关的,因为从路径 A 中删除的记录也会有意地从路径 B 中删除,但是 SQL 考虑到了最坏的情况(即查找表可能包含更多数据,成为 FK 目标另一个(单独的)表,或任何其他方式的数据可能会丢失。)
【解决方案2】:

如果您允许级联删除,删除其 UserId 出现在其他用户的 UserReferredId 字段中的人也会导致该用户被删除!我怀疑您想要的是将 UserReferredId 的值设置为 null 如果与其绑定的用户被删除。

有多种方法,从删除命令上的表触发器到使用存储过程进行删除。忽略触发器是邪恶的论点,可以创建类似的东西:

删除后在用户上创建触发器 clearUserReferredIdOnUserDelete 作为 update users set UserReferredId = null where UserReferredId in (select userid from deleted)

这是未经测试的,但应该很接近。

P

【讨论】:

  • 如果其中一个用户被删除,那么他们拥有的任何关系也应该被删除——不要设置为空。由于两列都在任何关系的 FK 端,我看不出它们如何导致其他任何内容被删除。它们只能因删除 User 中的一行而被删除。
【解决方案3】:

考虑到这一点,我开始认为这个问题与循环级联路径的关系不大,而可能与多个级联路径有关。

虽然我的联接表中的两个 UserID 总是不同的,但没有什么可以阻止它们相同。如果他们都引用同一个用户,并且该用户被删除,则连接表将有多个级联路径。

【讨论】:

    猜你喜欢
    • 2016-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    相关资源
    最近更新 更多