【问题标题】:Deleting tables with referential integrity - get REFERENCE constraint删除具有参照完整性的表 - 获取 REFERENCE 约束
【发布时间】:2021-04-21 23:52:20
【问题描述】:

我想删除一个包含博客评论和博客评论回复的用户(父表)

我将其编码为首先删除 BlogCommentReply(BlogComment 的子项),然后是 BlogComment(BlogCommentReply 的父项),然后是用户(两者的父项)。

我得到错误:

DELETE 语句与 REFERENCE 约束“FK_BlogCommentReply_UserId”冲突。冲突发生在数据库“DBGbngDev”、表“dbo.BlogCommentReply”、列“UserId”中。

我在 BlogCommentReply 和 BlogComment 表上有 FK 键。


1.) 我是否正确创建了表结构? 2.) 我需要级联 - 为什么? 3.) 删除代码顺序是否正确? _ 我相信直到
首先删除孩子。对吗?


表创建:

CREATE TABLE [dbo].[User]
(
   [UserId] [int] IDENTITY(1,1) NOT NULL, -- PK
   other columns....      
   CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
   (
     [UserId] ASC
   ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = 
           ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
          ) ON [PRIMARY]
   GO

CREATE TABLE [dbo].[BlogComment]
(
  [BlogCommentId] [int] IDENTITY(1,1) NOT NULL,      -- PK      
  [UserId] [int] NOT NULL,                           -- FK
  other columns....   
  CONSTRAINT [PK_BlogComment] PRIMARY KEY CLUSTERED
  (
    [BlogCommentId] ASC
  ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
         ) ON [PRIMARY]
  GO

  ALTER TABLE [dbo].[BlogComment] WITH CHECK ADD CONSTRAINT [FK_BlogComment_UserId] FOREIGN 
  KEY([UserId]) REFERENCES [dbo].[User] ([UserId])
  GO

CREATE TABLE [dbo].[BlogCommentReply]
(
  [BlogCommentReplyId] [int] IDENTITY(1,1) NOT NULL, -- PK      
  [UserId] [int] NOT NULL,                           -- FK
  [BlogCommentId] [int] NOT NULL,                    -- FK    
  other columns.... 
  CONSTRAINT [PK_BlogCommentReply] PRIMARY KEY CLUSTERED
  (
     [BlogCommentReplyId] ASC
  ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = 
           ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
         ) ON [PRIMARY]
  GO

  ALTER TABLE [dbo].[BlogCommentReply] WITH CHECK ADD CONSTRAINT [FK_BlogCommentReply_UserId] FOREIGN 
  KEY([UserId]) REFERENCES [dbo].[User] ([UserId])
  GO

 ALTER TABLE [dbo].[BlogCommentReply] WITH CHECK ADD CONSTRAINT [FK_BlogCommentReply_BlogCommentId] 
 FOREIGN KEY([BlogCommentId]) REFERENCES [dbo].[BlogComment] ([BlogCommentId])
 GO

执行删除的存储过程(为讨论而简化):

DELETE dbo.BlogCommentReply
FROM dbo.BlogComment a
WHERE ( BlogCommentReply.BlogCommentId = a.BlogCommentId AND BlogCommentReply.UserId = @a_UserId )

DELETE dbo.BlogComment
WHERE UserId = @a_UserId

DELETE dbo.[User]
WHERE ( UserId = @a_UserId )

【问题讨论】:

    标签: sql-server


    【解决方案1】:

    您的 FK 似乎正在完成他们的工作,并阻止您在从 BlogCommentReply 删除数据时创建孤立行。

    BlogCommentReply 中的第一个 DELETE 可以重写为两个语句以使其正常工作:

    -- Remove replies added by the deleted user
    DELETE
      FROM  dbo.BlogCommentReply
      WHERE (UserId = @a_UserId)
    
    -- Remove blog comment replies added by other users creating replies to a comment made by the deleted user
    DELETE
      FROM  dbo.BlogCommentReply
      WHERE (BlogCommentId IN (
                              SELECT  BlogCommentId
                                FROM  BlogComment
                                WHERE (UserId = @a_UserId)
                              ))
    

    在第一条语句中,您只是尝试从 BlogCommentReply 中删除使用 FK 到 User 表的行。

    在第二个语句中,您删除对将被删除的博客评论的任何回复。

    针对您的具体问题:

    1.我是否正确创建了表结构?

    看起来不错,虽然有几种方法可以达到同样的效果。

    2。我需要级联 - 为什么?

    没有。 Cascade 消除了糟糕设计和懒惰开发的恶臭。尝试 避免他们(注意这是一个意见不是事实陈述)。

    this question中有一些有趣的地方。

    3.删除代码顺序是否正确?

    是的,按关键优先顺序从表中删除。

    4.我相信只有先删除子表才能删除父表。对吗?

    确实是的,没有正确的级联删除,并且在您的 在这种情况下,抛出的错误表明 数据库是健全的。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 2018-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多