web-dev-qa-db-ja.com

同じ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レコードとそれが依存するユーザーレコードの両方)を削除することに興味があります。私のソリューションは最初にEntity Frameworkコードであり、双方向の関係により複数のカスケードパスが作成されるため、カスケードをオンにできません。

理想的には、次のようなものが欲しいです:

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

構文的にはこれはうまくいきませんが、このようなことが可能かどうか興味がありますか?

29
bwerks

いいえ、複数のステートメントを実行する必要があります。

2つのテーブルから削除する必要があるため、一致する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)
36
sgeddes

あなたが言う方法はMY SQL butnotfor SQL SERVER

「deleted」擬似テーブルを使用して、2つのテーブルから一度に値を削除できます。たとえば、

 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;

簡単な説明については、こちらをご覧ください リンク

削除されたテーブルの使用を知るために、あなたはこれに従うことができます 挿入および削除されたテーブルの使用

3
Rajesh

私が考えることができる唯一の方法は、論理的に双方向外部キーを手続きの方法で壊すことです。

visualization stateまたは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)
    REFERENCESユーザー(Id);

  4. Users列に追加

    ALTER TABLEユーザーADD 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操作になるため、このアプローチはパフォーマンスに影響を与えます。

2
Luis LL

トランザクションで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

または、同じためにストアプロシージャを使用することもできます トランザクションでのストアドプロシージャの使用:

1
uma

T-SQLを使用して外部キーを作成する場合は、ON DELETE CASCADEオプションを外部キーに追加する必要があります。

Code Snippet 

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

ON DELETE CASCADE;
1
Nagu