2013-07-09 33 views
27

有可能使用連接語句來限定設置爲要刪除,如下面的刪除:是否可以從同一個SQL語句中的多個表中刪除?

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

在語法上,這並不工作,但我很好奇,如果這樣的事情是可能的?

+3

不,DML語句只能影響一個表。您的選擇是刪除其中一個約束(並可能使用觸發器強制執行)。 –

+2

我認爲你需要在你的問題中弄清楚你有外鍵指向兩個方向。 –

+0

@AaronBertrand:謝謝 - 這是我正在尋找的答案:DML語句只能影響一個表,因此我想要的是不可能的。我們必須找出解決這個問題的另一種方法。如果你寫了一個這樣的答案,我會標記它。 – bwerks

回答

33

不,你需要運行多個語句。

因爲你需要從兩個表中刪除,請考慮創建匹配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) 
+0

我認爲這個問題是一個雙向的外鍵,在這種情況下單獨的語句不會工作(雞+雞蛋)。 –

+0

如果是這種情況,那麼在刪除運行後刪除約束並將其添加回來也可以。 – user2480596

+2

我不認爲EF-Code First允許您即時禁用/啓用約束,它可能不是高併發環境中的最佳解決方案。如果你打算一直關閉這個約束,那麼有什麼關係呢? –

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

使用
+0

您的意思是,「您說的方式可能在MY SQL中,但*不適用於SQL SERVER」? –

+0

@EdwardBrey是的,我的意思是隻有... – Rajesh

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 KEYNOCHECK

    ALTER TABLE LinkingTable WITH NOCHECK
    外鍵(U_ComesFrom_U_id)
    參考用戶(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操作。

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:

0

如果通過T-SQL創建外鍵,你必須附加的ON DELETE CASCADE選項到外鍵:

Code Snippet 

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

ON DELETE CASCADE; 
相關問題