我可以在一个语句中删除两个表中的条目吗?

Can I delete entries from two tables in one statement?

我必须从两个 table 中的每一个中删除一行,它们通过 ID 链接但没有正确的 PK - FK 关系(此数据库没有外键!)

table 之间具有假定的 1-1 关系。我不知道为什么不把它们放在同一个 table 但我不能随意更改它。

PersonId | Name | OwnsMonkey
----------------------------
    1       Jim       true
    2       Jim       false
    3       Gaz       true

信息

PersonId |    FurtherInfo
-----------------------------
    1       Hates his monkey
    2        Wants a monkey
    3       Loves his monkey

要决定删除什么,我必须找到一个用户名以及他们是否拥有一只猴子:

Select PersonId from People where Name = 'Jim' and OwnsMonkey = 'false'

所以我正在使用这个想法做两个单独的语句,先从 Info 中删除,然后从 People

中删除
delete from Info where PersonId = (Select PersonId from People where Name = 'Jim' and OwnsMonkey = 'false');

delete from People where PersonId = (Select PersonId from People where Name = 'Jim' and OwnsMonkey = 'false');

我找到了一个有希望的答案here on Whosebug

delete      a.*, b.*
from        People a
inner join  Info b
where       a.People = b.Info
            and a.PersonId = 
            (Select PersonId from People where Name = 'Jim' and OwnsMonkey = 'false')

但它在 Sql 服务器 (2012) 中给出了语法错误,我也尝试过不使用别名,但似乎无法同时删除两个 table

Can I delete entries from two tables in one statement?

没有。一条语句只能从 MS SQL 服务器中的一个 table 中删除行。

您提到的关于 MySQL 和 MySQL 的答案确实允许用一条语句从多个 table 中删除,如 MySQL docs. MS SQL Server doesn't support this, as can be seen in the docs.在 SQL 服务器的 DELETE 语句中没有包含多个 table 的语法。如果您尝试从视图中删除,而不是 table,也有一个限制:

The view referenced by table_or_view_name must be updatable and reference exactly one base table in the FROM clause of the view definition.


I was hoping to avoid two separate statements on the off-chance the second doesn't work for whatever reason, interrupted - concurrency really, I guess the TRY/CATCH will work well for that.

这就是 交易 的目的。 您可以在一个事务中放置多个语句,它们要么都成功,要么都失败。全有或全无。

在你的情况下,你不仅可以,而且应该将两个 DELETE 语句都放在一个事务中。

TRY/CATCH 有助于以更可控的方式处理可能的错误,但主要概念是“事务”。

BEGIN TRANSACTION

delete from Info where PersonId = (Select PersonId from People where Name = 'Jim' and OwnsMonkey = 'false');

delete from People where PersonId = (Select PersonId from People where Name = 'Jim' and OwnsMonkey = 'false');

COMMIT

我强烈推荐阅读 Erland Sommarskog 的一篇很棒的文章 Error and Transaction Handling in SQL Server


如果你想变得狡猾,像这样:

WITH
CTE
AS
(
    SELECT
        Info.PersonId AS ID1, People.PersonId AS ID2
    FROM
        Info
        INNER JOIN People ON Info.PersonId = People.PersonId
)
DELETE FROM CTE
WHERE ID1 = 1;

你会得到一个错误:

View or function 'CTE' is not updatable because the modification affects multiple base tables.

或者像这样:

WITH
CTE
AS
(
    SELECT
    PersonId
    FROM Info

    UNION ALL

    SELECT
    PersonId
    FROM People
)
DELETE FROM CTE
WHERE PersonId = 1;

你会得到另一个错误:

View 'CTE' is not updatable because the definition contains a UNION operator.