33

可以使用连接语句来限定要删除的集合进行删除,例如:

DELETE J
FROM Users U
inner join LinkingTable J on U.id = J.U_id
inner join Groups G on J.G_id = G.id

WHERE G.Name = 'Whatever'
and U.Name not in ('Exclude list')

但是,我有兴趣删除连接条件的两边——LinkingTable它所依赖的记录和用户记录。我无法打开级联,因为我的解决方案首先是实体框架代码,并且双向关系产生了多个级联路径。

理想情况下,我想要类似的东西:

DELETE J, U
FROM Users U
inner join LinkingTable J on U.id = J.U_id
...

从语法上讲这行不通,但我很好奇这样的事情是否可能?

4

5 回答 5

42

不,您需要运行多个语句。

因为您需要从两个表中删除,请考虑创建一个匹配 id 的临时表:

SELECT U.Id INTO #RecordsToDelete
FROM Users U
   JOIN LinkingTable J ON U.Id = J.U_Id
...

然后从每个表中删除:

DELETE FROM Users 
WHERE Id IN (SELECT Id FROM #RecordsToDelete)

DELETE FROM LinkingTable
WHERE Id IN (SELECT Id FROM #RecordsToDelete)
于 2013-07-09T03:06:17.963 回答
4

你说的方式是可能的,MY SQL不是为了SQL SERVER

您可以使用“已删除”伪表一次删除两个表中的值,例如,

 begin transaction;

 declare @deletedIds table ( samcol1 varchar(25) );

 delete #temp1
 output deleted.samcol1 into @deletedIds
 from #temp1 t1
 join #temp2 t2
 on t2.samcol1 = t1.samcol1

 delete #temp2
 from #temp2 t2
 join @deletedIds d
 on d.samcol1 = t2.samcol1;

 commit transaction;

对于简要说明,您可以查看此链接

并了解已删除表的使用,您可以按照此使用插入和删除的表

于 2013-07-09T04:39:48.793 回答
2

我能想到的唯一方法是以程序方式在逻辑上打破双向外键。

如果您没有一些visualization状态标志或status

就像是

  1. INSERT对用户不可见的虚拟行(类似于 Id = -1虚拟值)
  2. 添加到LinkingTable替代列以指向Users,我将其命名为U_ComesFrom

    ALTER TABLE LinkingTagble ADD U_ComesFrom_U_id INT DEFAULT(-1)

  3. 添加FOREIGN KEY一个NOCHECK

    ALTER TABLE LinkingTable WITH NOCHECK
    FOREIGN KEY (U_ComesFrom_U_id)
    REFERENCES Users (Id) ;

  4. 添加到Users

    ALTER TABLE 用户添加 MarkedForDeletion BIT NOT NULL DEFAULT(0)

然后你的 SQL 看起来像

BEGIN TRANSACTION
    UPDATE J
    SET U_Comes_From_U_id = U_ID, U_id = -1 -- or some N/R value that you define in Users
    FROM Users U
    inner join LinkingTable J on U.id = J.U_id
    inner join Groups G on J.G_id = G.id
    WHERE G.Name = 'Whatever'
    and U.Name not in ('Exclude list')

    UPDATE U
    SET MarkedForDeletion = 1
    FROM Users
    inner join LinkingTable J on U.id = J.U_ComesFrom_U_id 
    WHERE U_id > 0

    DELETE FROM LinkingTable 
    WHERE U_ComesFrom_U_id > 0

    DELETE FROM Users
    WHERE MarkedForDeletion = 1

COMMIT

这种方法会影响性能,因为每个事务将是每个双向键至少 4 个 DML 操作。

于 2013-07-09T05:33:01.977 回答
1

将 TRY CATCH 与事务一起使用

BEGIN TRANSACTION
BEGIN TRY
    DELETE from A WHERE id=1

    DELETE FROM b WHERE id=1

    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH

或者您也可以将存储过程用于相同的 Using Stored Procedure With Transaction:

于 2013-07-09T05:56:46.320 回答
1

如果您通过 T-SQL 创建外键,则必须将 ON DELETE CASCADE 选项附加到外键:

Code Snippet 

ALTER TABLE <tablename>
ADD CONSTRAINT <constraintname> FOREIGN KEY (<columnname(s)>)
REFERENCES <referencedtablename> (<columnname(s)>)

ON DELETE CASCADE;
于 2014-03-31T09:29:40.957 回答