sql - DELETE 语句与 REFERENCE 约束“FK_BlogCommentReply_BlogCommentId”冲突
问题描述
我有一个博客并保持简单讨论,主要表格是博客、博客评论、博客评论回复和用户。
博客属于用户。评论属于博客/用户。评论回复属于博客/评论/用户。
我想删除一个用户 - UserId = 5。
我的删除用户存储过程按以下顺序删除(包装在事务中):
- 博客评论回复
- 博客评论
- 博客(如果用户只是博客的作者)
- 用户
它删除用户的 BlogCommentReply 中的条目,然后尝试删除用户的 BlogComment 中的条目。
然后我得到错误:
The DELETE statement conflicted with the REFERENCE constraint "FK_BlogCommentReply_BlogCommentId".
The conflict occurred in database "DBGbngDev", table "dbo.BlogCommentReply", column
'BlogCommentId'.
它仍然认为 BlogCommentReply 表中有一个条目。
这是存储过程的执行,其中包含调试选择,以表明它删除了 BlogCommentReply 条目,但随后在删除 BlogComment 时失败。
表定义:
----------------------- BlogComment table (parent to blogCommentReply)
CREATE TABLE [dbo].[BlogComment](
[BlogCommentId] [int] IDENTITY(1,1) NOT NULL,
[UserId] [int] NOT NULL,
[BlogId] [int] NOT NULL,
[BlogCommentContent] [varchar](max) NOT NULL,
[LikeCount] [int] NOT NULL,
[DisLikeCount] [int] NOT NULL,
[DateTimeOfBlogComment] [datetime] NOT NULL,
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] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[BlogComment] WITH CHECK ADD CONSTRAINT [FK_BlogComment_BlogId] FOREIGN
KEY([BlogId])
REFERENCES [dbo].[Blog] ([BlogId])
GO
ALTER TABLE [dbo].[BlogComment] CHECK CONSTRAINT [FK_BlogComment_BlogId]
GO
ALTER TABLE [dbo].[BlogComment] WITH CHECK ADD CONSTRAINT [FK_BlogComment_UserId] FOREIGN
KEY([UserId])
REFERENCES [dbo].[User] ([UserId])
GO
ALTER TABLE [dbo].[BlogComment] CHECK CONSTRAINT [FK_BlogComment_UserId]
GO
----------------------- BlogCommentReply table (child)
CREATE TABLE [dbo].[BlogCommentReply](
[BlogCommentReplyId] [int] IDENTITY(1,1) NOT NULL,
[UserId] [int] NOT NULL,
[BlogCommentId] [int] NOT NULL,
[BlogId] [int] NOT NULL,
[BlogCommentReplyContent] [varchar](max) NOT NULL,
[LikeCount] [int] NOT NULL,
[DisLikeCount] [int] NOT NULL,
[DateTimeOfBlogCommentReply] [datetime] NOT NULL,
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] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[BlogCommentReply] WITH CHECK ADD CONSTRAINT [FK_BlogCommentReply_BlogCommentId]
FOREIGN KEY([BlogCommentId])
REFERENCES [dbo].[BlogComment] ([BlogCommentId])
GO
ALTER TABLE [dbo].[BlogCommentReply] CHECK CONSTRAINT [FK_BlogCommentReply_BlogCommentId]
GO
ALTER TABLE [dbo].[BlogCommentReply] WITH CHECK ADD CONSTRAINT [FK_BlogCommentReply_BlogId] FOREIGN
KEY([BlogId])
REFERENCES [dbo].[Blog] ([BlogId])
GO
ALTER TABLE [dbo].[BlogCommentReply] CHECK CONSTRAINT [FK_BlogCommentReply_BlogId]
GO
ALTER TABLE [dbo].[BlogCommentReply] WITH CHECK ADD CONSTRAINT [FK_BlogCommentReply_UserId] FOREIGN
KEY([UserId])
REFERENCES [dbo].[User] ([UserId])
GO
ALTER TABLE [dbo].[BlogCommentReply] CHECK CONSTRAINT [FK_BlogCommentReply_UserId]
GO
删除存储过程的提取部分 (@a_UserId = 5):
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- Step 6. Get the number of blog comments replys for the user.
-- Note: there may not be any.
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SELECT @BlogCommentReplysCount = Count(*)
FROM dbo.BlogCommentReply
WHERE ( UserId = @a_UserId )
SELECT @ReturnCode = @@ERROR
IF @ReturnCode <> 0
BEGIN
ROLLBACK TRANSACTION
SELECT @Message = 'Critical Error - procedure DeleteBlog failed during the select of BlogCommentReply. User id: ' + CAST(@a_UserId AS VARCHAR) + '. '
RAISERROR (@Message, 16, 1)
END
SELECT '@BlogCommentReplysCount: ' + CAST(@BlogCommentReplysCount AS VARCHAR) + '. '
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- Step 7. Delete the BlogCommentReply entries for the user.
-- Note: the user may not have made any.
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DELETE dbo.BlogCommentReply
WHERE ( UserId = @a_UserId )
SELECT @ReturnCode = @@ERROR,
@RowCount = @@ROWCOUNT
IF @ReturnCode <> 0 AND @RowCount > 0
BEGIN
ROLLBACK TRANSACTION
SELECT @Message = 'Critical Error - procedure DeleteBlog failed during the delete of BlogCommentReply. User id: ' + CAST(@a_UserId AS VARCHAR) + '. '
RAISERROR (@Message, 16, 1)
END
SELECT 'Deleted BlogCommentReply'
SELECT '@ReturnCode: ' + CAST(@ReturnCode AS VARCHAR) + '. '
SELECT '@RowCount: ' + CAST(@RowCount AS VARCHAR) + '. '
SELECT '@a_UserId: ' + CAST(@a_UserId AS VARCHAR) + '. '
SELECT Count(*) as AFTERDELETE
FROM dbo.BlogCommentReply
WHERE ( UserId = @a_UserId )
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- Step 8. Get the number of blog comments for this user.
-- Note: there may not be any.
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SELECT @BlogCommentsCount = Count(*)
FROM dbo.BlogComment
WHERE ( UserId = @a_UserId )
SELECT @ReturnCode = @@ERROR
IF @ReturnCode <> 0
BEGIN
ROLLBACK TRANSACTION
SELECT @Message = 'Critical Error - procedure DeleteBlog failed during the select of BlogComment. User id: ' + CAST(@a_UserId AS VARCHAR) + '. '
RAISERROR (@Message, 16, 1)
END
SELECT '@BlogCommentsCount: ' + CAST(@BlogCommentsCount AS VARCHAR) + '. '
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- Step 9. Delete the BlogComment entries for the user.
-- Note: the user may not have made any.
--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SELECT Count(*) as BEFORE
FROM dbo.BlogComment
WHERE ( UserId = @a_UserId )
SELECT 'Going to delete BlogComment'
DELETE dbo.BlogComment
WHERE ( UserId = @a_UserId )
SELECT @ReturnCode = @@ERROR,
@RowCount = @@ROWCOUNT
IF @ReturnCode <> 0 AND @RowCount > 0
BEGIN
ROLLBACK TRANSACTION
SELECT @Message = 'Critical Error - procedure DeleteBlog failed during the delete of BlogComment. User id: ' + CAST(@a_UserId AS VARCHAR) + '. '
RAISERROR (@Message, 16, 1)
END
SELECT 'Deleted BlogComment'
解决方案
我认为最好有完整的存储过程脚本来检查错误,但同时我猜问题出在此处:
DELETE dbo.BlogCommentReply
WHERE ( UserId = @a_UserId )
好的,它正在删除相关用户(即@a_UserId = 5)拥有的所有评论回复。
但看看你的脚本的其余部分:
DELETE dbo.BlogComment
WHERE ( UserId = @a_UserId )
它正在删除所有用户的评论,而他们可能对其他用户有一些其他评论回复并且他们没有被删除。所以我认为问题就在这里。
也许最好将第一个删除部分更改为:
DELETE dbo.BlogCommentReply
WHERE ( UserId = @a_UserId )
DELETE dbo.BlogCommentReply
FROM [dbo].[BlogComment]
WHERE dbo.BlogCommentReply.BlogCommentId=[dbo].[BlogComment].BlogCommentId
AND [dbo].[BlogComment].UserId=@a_UserId
推荐阅读
- ios - React-Native iOS - 如何在启动屏幕之后显示视图控制器,然后再初始化反应原生桥(iOS)
- python - Edabit 任务未显示正确结果
- azure-devops - Azure DevOps 项目管道无法从不同项目中的工件源访问 NuGet 包
- linux - 如何知道 Libreoffice 安装在 Docker 映像中的什么位置?
- kerberos - linux docker容器中的Windows身份验证
- c# - 带有 xamarin 的免费地图(商业用途)
- sql-server - 将 id 从一个表复制到另一个
- c# - 触发器不适用于自定义控件图像按钮 wpf
- html - 为什么在这里使用(本地文件)chrome不播放音频?
- c# - WPF - 在异步任务的回调中更改 UI 文化