是否可以从同一SQL语句中的多个表中删除?

时间:2013-07-09 02:54:33

标签: sql sql-server delete-row cascading-deletes

可以使用join语句删除以限定要删除的集合,例如:

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
...

从句法上来说这没有用,但我很好奇这样的事情是否可行?

5 个答案:

答案 0 :(得分:35)

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

因为您需要从两个表中删除,所以请考虑创建匹配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)

答案 1 :(得分:3)

您在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;

简要说明您可以查看此Link

并了解使用已删除的表格,您可以按照此Using the inserted and deleted Tables

进行操作

答案 2 :(得分: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
    外键(U_ComesFrom_U_id)
    参考用户(Id);

  4. 添加到Users

    ALTER TABLE用户添加MarkedForDeletion BIT NOT NULL默认值(0)

  5. 然后你的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操作。

答案 3 :(得分: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

或 你也可以使用Store程序 Using Stored Procedure With Transaction:

答案 4 :(得分: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;