SQL ServerでINNER JOINを使用して複数のテーブルから削除する方法


117

MySQLでは、構文を使用できます

DELETE t1,t2 
FROM table1 AS t1 
INNER JOIN table2 t2 ...
INNER JOIN table3 t3 ...

SQL Serverで同じことをするにはどうすればよいですか?

回答:


119

この例では、「削除された」疑似テーブルを利用できます。何かのようなもの:

begin transaction;

   declare @deletedIds table ( id int );

   delete from t1
   output deleted.id into @deletedIds
   from table1 as t1
    inner join table2 as t2
      on t2.id = t1.id
    inner join table3 as t3
      on t3.id = t2.id;

   delete from t2
   from table2 as t2
    inner join @deletedIds as d
      on d.id = t2.id;

   delete from t3
   from table3 as t3 ...

commit transaction;

もちろん、「削除された出力」を実行できます。3番目のテーブルに結合する何かが必要な場合は、2番目の削除でも同様です。

ちなみに、insertステートメントでInserted。*を実行し、UpdateステートメントでInserted。*とDeleted。*を実行することもできます。

編集: また、table2 + 3から削除するトリガーをtable1に追加することを検討しましたか?暗黙のトランザクション内にいることになり、「挿入された」および「削除された」疑似テーブルも使用可能になります。


2
内部結合を使用してこの余分なテキストをすべて処理するのではなく、単にDELETE FROM table1 WHERE id = xを実行してから、次のテーブルから削除する方が良いですか?基本的に、内部結合をスキップするには、2つの単純なクエリが必要です。それとも、この方法の方が効率的ですか。
Colandus 2013年

where句がどれだけ複雑かによって異なると思います。複雑なものの場合、1回しか発生しないため、これはより良い方法です。ただし、多くの行に影響を与える単純なwhere句の場合、テーブル変数に多くのIDを保持する必要がないため、提案はおそらくより効率的です。
ジョンギブ2013

@JohnGibb、この答えはどのように機能しますか?MySQLの開発者が理解できるように、この答えを説明できますか?
Pacerier、2015

@Pacerier私はMySQLにあまり詳しくありません。最初の削除はtable1からの削除のみですが、削除されたIDを変数に保存しています。その後の二つの文どの変数が表2と表3から関連する行を削除することを用途
ジョン・ギブ

@JohnGibb、これ明らかになりました。あなたはそれを答えに含めるべきです。
Pacerier 2015

15
  1. テーブルの関係にカスケード削除をいつでも設定できます。

  2. 複数の削除を1つのストアドプロシージャにカプセル化できます。

  3. トランザクションを使用して、1つの作業単位を確保できます。


3
結合ステートメントで削除することは間違いなく可能です。一度に複数のテーブルから削除したいだけです。
バイロンウィットロック

不正解、ジョインは削除で使用できる
rboarman

ad 1.)それは真実ではなく、常に可能であるとは限りません。サイクル削除や複数のカスケードパスなど、カスケード削除を設定できないシナリオがいくつかあります。(たとえば、stackoverflow.com
/ a / 3548225/108374を

15

SQL ServerのDELETEのFROM句でJOIN構文を使用できますが、それでも最初のテーブルからのみ削除できます。これは、サブクエリに代わる独自のTransact-SQL拡張機能です。

ここのから

 -- Transact-SQL extension
 DELETE 
   FROM Sales.SalesPersonQuotaHistory 
     FROM Sales.SalesPersonQuotaHistory AS spqh INNER JOIN 
          Sales.SalesPerson AS sp ON spqh.BusinessEntityID = sp.BusinessEntityID
    WHERE sp.SalesYTD > 2500000.00;

3
例D:DELETE FROM Sales.SalesPersonQuotaHistory FROM Sales.SalesPersonQuotaHistory AS spqh INNER JOIN Sales.SalesPerson AS sp ON spqh.BusinessEntityID = sp.BusinessEntityID WHERE sp.SalesYTD> 2500000.00;
マークA

11

マスターテーブルからいくつかのレコードを削除し、2つの詳細テーブルから対応するレコードを削除する例:

BEGIN TRAN

  -- create temporary table for deleted IDs
  CREATE TABLE #DeleteIds (
    Id INT NOT NULL PRIMARY KEY
  )

  -- save IDs of master table records (you want to delete) to temporary table    
  INSERT INTO #DeleteIds(Id)
  SELECT DISTINCT mt.MasterTableId
  FROM MasterTable mt 
  INNER JOIN ... 
  WHERE ...  

  -- delete from first detail table using join syntax
  DELETE d
  FROM DetailTable_1 D
  INNER JOIN #DeleteIds X
    ON D.MasterTableId = X.Id


  -- delete from second detail table using IN clause  
  DELETE FROM DetailTable_2
  WHERE MasterTableId IN (
    SELECT X.Id
    FROM #DeleteIds X
  )


  -- and finally delete from master table
  DELETE d
  FROM MasterTable D
  INNER JOIN #DeleteIds X
    ON D.MasterTableId = X.Id

  -- do not forget to drop the temp table
  DROP TABLE #DeleteIds

COMMIT

1
あなたは使用することができSELECT INTO #DeleteIds代わりにCREATE TABLE 'DeleteIds続きますかINSERT INTO 'DeleteIds...
Caltor、

9

MySQLでそれが本当に可能ですか?それはt1とt2を削除しますか?または私は質問を誤解しました。

ただし、複数の結合条件を持つtable1を削除するだけの場合は、削除するテーブルにエイリアスを設定しないでください。

この:

DELETE t1,t2 
FROM table1 AS t1 
INNER JOIN table2 t2 ...
INNER JOIN table3 t3 ...

MSSQLで機能するには、次のように記述します。

DELETE table1
FROM table1 
INNER JOIN table2 t2 ...
INNER JOIN table3 t3 ...

他の2つの一般的なRDBMSがどのように削除操作を行うかを対比してください。

http://mssql-to-postgresql.blogspot.com/2007/12/deleting-duplicates-in-postgresql-ms.html


そこでのSQL Serverのヒントのおかげで、私はそれらの線に沿ってSQLを微調整する必要がありました。
Pauk、

7

基本的に、トランザクションで3つの削除ステートメントを作成する必要はありません。最初に子、次に親です。カスケード削除の設定は、これが1回限りのものではなく、その存在が既存のトリガー設定と競合しない場合に適しています。


私はそうする必要がないことを望んでいました。関係は親子関係ではないため、IDを一時テーブルに選択する必要があると思います。1つのテーブルの行がなくなると、他の行を取得する方法はありません。
バイロンウィットロック

3

SQLサーバーでは、結合を使用して複数のテーブルを削除する方法はありません。したがって、フォームの親を削除する前に、まず子から削除する必要があります。


2

これは、孤立したファイルを残さずにレコードを削除する別の方法です。

@user Table(keyValue int、someString varchar(10))を宣言します
@userに挿入
値(1、 '1値')

@userに挿入
値(2、 '2値')

@userに挿入
値(3、 '3値')

@password Table(keyValue int、詳細varchar(10))を宣言します
@passwordに挿入
値(1、 '1パスワード')
@passwordに挿入
値(2、 '2パスワード')
@passwordに挿入
値(3、 '3パスワード')

        -削除前
  @passwordから*を選択します。内部結合@user b
                on a.keyvalue = b.keyvalue
  select * into @deletedID from @user where keyvalue = 1-これは出力例のように機能します
  keyvalue = 1の@userを削除
  キー値が含まれている@passwordを削除します(#deletedidからキー値を選択します)

  -削除後-
  @passwordから*を選択します。内部結合@user b
                on a.keyvalue = b.keyvalue


2

すべて指摘されています。ただ、いずれかを使用しDELETE ON CASCADE、親にtableまたはから削除child-tableしますparent


子テーブルから親に削除するとはどういう意味ですか?質問や前述の回答で示されたような結合技術を使用することを意味しますか?
Imran Faruqi

1

Aaronがすでに指摘したように、削除動作をCASCADEに設定すると、親レコードが削除されると子レコードも削除されます。他の何らかの魔法を起こさせたくない場合(この場合、Aaronの応答のポイント2、3が役に立つでしょう)、内部結合で削除する必要がある理由はわかりません。


0

John Gibbの答えに基づいて、FK関係を持つ2つのテーブルのデータセットを削除するには、次のようにします。

--*** To delete from tblMain which JOINs to (has a FK of) tblReferredTo's PK  
--       i.e.  ON tblMain.Refer_FK = tblReferredTo.ID
--*** !!! If you're CERTAIN that no other rows anywhere also refer to the 
--      specific rows in tblReferredTo !!!
BEGIN TRAN;

    --*** Keep the ID's from tblReferredTo when we DELETE from tblMain
    DECLARE @tblDeletedRefs TABLE ( ID INT );
    --*** DELETE from the referring table first
    DELETE FROM tblMain 
    OUTPUT DELETED.Refer_FK INTO @tblDeletedRefs  -- doesn't matter that this isn't DISTINCT, the following DELETE still works.
    WHERE ..... -- be careful if filtering, what if other rows 
                --   in tblMain (or elsewhere) also point to the tblReferredTo rows?

    --*** Now we can remove the referred to rows, even though tblMain no longer refers to them.
    DELETE tblReferredTo
    FROM   tblReferredTo INNER JOIN @tblDeletedRefs Removed  
            ON tblReferredTo.ID = Removed.ID;

COMMIT TRAN;

-3
DELETE     TABLE1 LIN
FROM TABLE1 LIN
INNER JOIN TABLE2 LCS ON  CONDITION
WHERE CONDITION

2つ以上のテーブルからは削除されません。質問を理解してください
Kamran Shahid

-5

$ SQL = "FROM DELETE basic_tbleducation_tblpersonal_tbladdress_tbldepartment_tbl 使用した basic_tbleducation_tblpersonal_tbladdress_tbl、= = = = = '" $番号。。 "」「; $ rs = mysqli_query($ con、$ sql);department_tblb_ide_idp_ida_idd_id


書式を修正し、コードが機能する理由を簡単に説明してください。
ブライアンハーブスト2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.