【问题标题】:Having multiple foreign keys to same table with different on delete causes error对同一个表有多个外键但删除时不同会导致错误
【发布时间】:2021-03-31 11:23:56
【问题描述】:

我有一个简单的表,其中有 2 个外键指向同一个表中的不同用户:

CREATE TABLE [dbo].[InstallerDetails]
(
    [UserId] int NOT NULL PRIMARY KEY 
         FOREIGN KEY REFERENCES Users(Id) ON DELETE CASCADE,
    [AssignedSalesman] int NULL
         FOREIGN KEY REFERENCES Users(Id) ON DELETE SET NULL,
    ...some more columns
)

UserId 指向需要的用户,当该用户被删除时,我也想删除其详细信息。

AssignedSalesman 指向其他用户,这是可选的,我想在删除该用户时设置 null。

但是,这种结构会导致错误:

在表“InstallerDetails”上引入 FOREIGN KEY 约束“FK__Installer__Assig__6D0D32F4”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。

我不明白它如何导致循环。这真的是一个错误吗?有没有其他方法可以实现这种逻辑?

【问题讨论】:

  • 使用UserId作为主键和外键感觉很奇怪。当然,这使它成为 1:1 的关系,但这可能是原因吗?如果您在表上创建单独的主键列会发生什么。
  • 将 UserId 分离为 2 个字段不会改变任何事情,同样的错误。我这样做是因为有许多类型的用户可以有不同的字段集,并且我想确保每组详细信息都与其原始用户密切相关。
  • @ex4:这不一定很奇怪。在为弱实体建模时,主键也是外键是一个常见的概念。唯一的问题是弱实体并不经常“在野外”出现,因此这种主键和外键的组合在模式中很少见。

标签: sql sql-server


【解决方案1】:

这是众所周知的 SQL Server 行为,不允许从子级到父级的两个或多个 on delete 路径。例如,这将运行正常

CREATE TABLE [dbo].[InstallerDetails]
(
    [UserId] int not null PRIMARY KEY foreign key references Users(Id) on delete cascade
    ,[AssignedSalesman] int null foreign key references Users(Id) 
)

您可以使用触发器强制缺少on delete set null

【讨论】:

    【解决方案2】:

    一个例子:

    +-------+--------+--------------------+
    | RowID | UserId | [AssignedSalesman] |
    +-------+--------+--------------------+
    |     1 | userA  | userB              |
    |     2 | userB  | userC              |
    |     3 | userC  | userD              |
    +-------+--------+--------------------+
    

    如果你delete .. where RowID=1

    然后突然所有行都是空的。我想这就是 SQL Server 试图避免的。 (不过,我也希望能够停用此检查)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-06
      • 2017-11-08
      • 2021-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-12
      相关资源
      最近更新 更多