使用 SqlCommand 从多个表中删除

Posted

技术标签:

【中文标题】使用 SqlCommand 从多个表中删除【英文标题】:Delete from multiple tables with SqlCommand 【发布时间】:2021-03-12 13:26:54 【问题描述】:

当我尝试使用 INNER JOIN 从 2 个表中删除一整行时,出现底部显示的错误。我在网上搜索了,没有找到问题,所以我来这里寻求帮助。

代码如下:

    var delete = new SqlCommand("DELETE Posts, Comments FROM Posts INNER JOIN Comments ON Posts.PostId = Comments.PostId WHERE Posts.PostId = @PostId;");
    delete.Parameters.AddWithValue("@PostId", postId);
    _dataAccess.ExecuteQuery(delete);

我收到一条错误消息:

System.Data.SqlClient.SqlException: 'Incorrect syntax near ','.'

【问题讨论】:

类似这样的:this 或 this 这能回答你的问题吗? How do I delete from multiple tables using INNER JOIN in SQL server 【参考方案1】:

你的问题在SQL Statement,它是无效的。

你应该把语句分成两个:

先删除Comments,再删除Posts

顺序很重要

var deleteComments = new SqlCommand("DELETE Comments FROM Posts INNER JOIN Comments ON Posts.PostId = Comments.PostId WHERE Posts.PostId = @PostId;");
        deleteComments.Parameters.AddWithValue("@PostId", postId);
        _dataAccess.ExecuteQuery(deleteComments);
        
var deletePosts = new SqlCommand("DELETE Posts WHERE PostId= @PostId;");
        deletePosts.Parameters.AddWithValue("@PostId", postId);
        _dataAccess.ExecuteQuery(deletePosts);

另一种选择,使用一个语句:

var delete = new SqlCommand("DELETE Comments FROM Posts INNER JOIN Comments ON Posts.PostId = Comments.PostId WHERE Posts.PostId = @PostId; DELETE Posts WHERE PostId= @PostId;");
            delete.Parameters.AddWithValue("@PostId", postId);
            _dataAccess.ExecuteQuery(delete);

更多解释:

通过 SQL Studio (SSMS) 使用以下准备好的 SQL 脚本:

CREATE TABLE Posts (PostId  INT, PostText varchar(20))
CREATE TABLE Comments (CommentId INT, PostId INT, CommentText varchar(20))

INSERT INTO Posts VALUES (1, 'text')
INSERT INTO Comments VALUES (1,1, 'comment here')

当我运行你的 DELETE 语句时

DELETE Posts, Comments FROM Posts INNER JOIN Comments ON Posts.PostId = Comments.PostId WHERE Posts.PostId = 1

它给了我同样的错误

当我跑步时

DELETE Comments FROM Posts INNER JOIN Comments ON Posts.PostId = Comments.PostId WHERE Posts.PostId = 1;

DELETE Posts WHERE PostId = 1;

效果很好。

所以经验法则在这种情况下是先使用SSMS (MS SQL Studio)来测试你的SQL语句然后执行它在 C# 中。

【讨论】:

这可行,但我的利益相关者希望尽可能少的查询。并且在此它将与数据库建立 2 个单独的连接。有没有一种方法可以让我把它放在一个陈述中? 所以合并它们 @U8080 在这种情况下删除时不需要 INNER JOIN ,因为该表中已经有 PostId 。 INNER JOIN 将是额外的开销。 @JaapSmit 答案就在您的问题后面的评论中。 下次我将首先尝试 SSMS 上的 sql 语句,现在我认为它确实是处理这些情况的更好方法。【参考方案2】:

MSSQL Server 中没有选项可以在一个语句中从多个表中删除数据。所以,你DELETE Posts, Comments FROM的说法是不正确的。

您有两个选项可以将此外键设置为CASCADE DELETE,或者重写您的语句以删除这两个表中的数据,如下所示:

var delete = new SqlCommand("DELETE FROM Comments WHERE PostId = @PostId; 
                             DELETE FROM Posts WHERE PostId = @PostId;");
delete.Parameters.AddWithValue("@PostId", postId);
_dataAccess.ExecuteQuery(delete);

【讨论】:

【参考方案3】:

您的 MS SQL 查询不正确。如果要从多个表中删除,有两种选择:

    设置级联删除,其中一个表中的删除将自动导致从属表中的删除

    编写单独的删除查询,例如:

从评论中删除 PostId = @PostId 从 PostId = @PostId 的帖子中删除

但是,我建议您先通过 SQL Management Studio 测试您的查询,然后再尝试为它们开发代码。

【讨论】:

以上是关于使用 SqlCommand 从多个表中删除的主要内容,如果未能解决你的问题,请参考以下文章

带参数的 SqlCommand

从多个表中获取数据

如何使用 Where 子句从多个表中删除多行?

从多个 Access 表中删除记录

使用 C# 命令从多个 SQL 表中删除

如何使用 SqlCommand 返回多个结果集?