SQL sunucusunda INNER JOIN kullanarak birden çok tablodan nasıl silerim


117

MySQL'de sözdizimini kullanabilirsiniz

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

Aynı şeyi SQL Server'da nasıl yaparım?

Yanıtlar:


119

Bu örnekte "silinmiş" sözde tablodan yararlanabilirsiniz. Gibi bir şey:

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;

Açıkçası bir 'çıktı silindi' yapabilirsiniz. üçüncü masaya katılmak için bir şeye ihtiyacınız varsa ikinci silme işleminde de.

Bir yan not olarak, bir insert deyimine eklenmiş. * Ve bir güncelleme deyiminde hem eklenen. * Hem de silinen. * Ekleyebilirsiniz.

DÜZENLEME: Ayrıca, table2 + 3'ten silmek için table1'e bir tetikleyici eklemeyi düşündünüz mü? Örtük bir işlemin içinde olacaksınız ve ayrıca "eklenen " ve "silinmiş " sözde tablolar da mevcut olacak.


2
İç birleştirmeyi kullanmak ve tüm bu fazladan metnin üzerinden geçmek yerine, sadece tablo1 NEREDEN id = x'DEN SİLİN ve ardından sonraki tablodan silme daha mı iyi? Temel olarak, iç birleşimi atlamak sadece 2 basit sorguya ihtiyacım var .... Yoksa bu yöntem daha verimli mi?
Colandus

Sanırım bu, nerede cümlenizin ne kadar karmaşık olduğuna bağlı. Karmaşık biri için bu daha iyi olurdu çünkü sadece bir kez oluyor. Ancak, çok sayıda satırı etkileyen daha basit bir yan tümce için, bir tablo değişkeninde çok sayıda kimlik bulundurması gerekmediğinden teklifiniz muhtemelen daha verimli olacaktır.
John Gibb

@JohnGibb, bu cevap nasıl çalışıyor? Bu cevabı bir MySQL geliştiricisinin anlayabilmesi için açıklayabilir misiniz?
Pacerier

@Pacerier MySQL'e pek aşina değilim. Buradaki fikir, ilk silme işleminin yalnızca tablo1'den silinmesi, ancak silinen kimlikleri bir değişkene kaydetmesidir. Sonraki iki ifade, ilişkili satırları tablo2 ve tablo 3'ten silmek için bu değişkeni nasıl kullanır?
John Gibb

@JohnGibb, Şimdi bu açık. Bunu cevaba eklemelisin.
Pacerier

15
  1. Tabloların ilişkilerinde her zaman basamaklı silmeler ayarlayabilirsiniz.

  2. Birden çok silme işlemini tek bir saklı yordamda kapsülleyebilirsiniz.

  3. Bir birim iş sağlamak için bir işlem kullanabilirsiniz.


3
Bir join deyiminde silmek kesinlikle mümkün, sadece bir seferde birden fazla tablodan silmek istiyorum.
Byron Whitlock

Yanlış cevap, birleştirmeler silme ile kullanılabilir
rboarman

ad 1.) Bu doğru değil, her zaman mümkün olmayabilir. Basamaklı silme işlemlerini ayarlayamayacağınız bazı senaryolar vardır, örneğin döngüler veya çoklu basamaklı yollar. ( örneğin stackoverflow.com/a/3548225/108374'e bakın )
Tom Pažourek

15

JOIN sözdizimini, SQL Server'daki DELETE içindeki FROM yan tümcesinde kullanabilirsiniz, ancak yine de yalnızca ilk tablodan silersiniz ve alt sorguya alternatif olan tescilli Transact-SQL uzantısıdır.

Buradaki örnekten :

 -- 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
Örnek D: Sales.SalesPersonQuotaHistory'den Sales.SalesPersonQuotaHistory'den SİLİN AS spqh INNER JOIN Sales.SalesPerson AS sp on spqh.BusinessEntityID = sp.BusinessEntityID WHERE sp.SalesYTD> 2500000.00;
Mark A

11

Bazı kayıtları ana tablodan ve karşılık gelen kayıtları iki ayrıntı tablosundan silme örneği:

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
Takip etmek SELECT INTO #DeleteIdsyerine kullanabilir misin ? CREATE TABLE 'DeleteIdsINSERT INTO 'DeleteIds...
Caltor

9

Merak ediyorum .. MySQL'de bu gerçekten mümkün mü? t1 ve t2'yi silecek mi? ya da sadece soruyu yanlış anladım.

Ancak birden çok birleştirme koşuluna sahip table1'i silmek istiyorsanız, silmek istediğiniz tablonun adını değiştirmeyin.

bu:

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

MSSQL'de çalışması için şöyle yazılmalıdır:

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

diğer iki ortak RDBMS'nin silme işlemini nasıl yaptığını karşılaştırmak için:

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


Oradaki SQL Server ipucu için teşekkürler, SQL'i bu satırlar boyunca ayarlamak zorunda kaldım.
Pauk

7

Temel olarak, hayır, bir işlemde önce çocuklar ve sonra ebeveynler olmak üzere üç silme ifadesi yapmanız gerekmez. Basamaklı silme ayarlamak, bu tek seferlik bir şey değilse ve varlığı mevcut herhangi bir tetikleyici kurulumuyla çakışmayacaksa iyi bir fikirdir.


Bunu yapmak zorunda olmadığımı umuyordum, sanırım kimliği geçici bir tabloya seçmem gerekecek çünkü ilişki bir ebeveyn çocuk değil. Bir tablodaki satırlar gittiğinde, diğer satırları almanın bir yolu yoktur.
Byron Whitlock

3

SQL sunucusunda birleştirmeyi kullanarak birden çok tabloyu silmenin bir yolu yoktur. Bu nedenle, form ebeveynini silmeden önce çocuktan silmeniz gerekir.


2

Bu, öksüz bırakmadan kayıtları silmenin alternatif bir yoludur.

@User Tablosu Bildir (keyValue int, someString varchar (10))
@user'a ekle
değerler (1, "1 değer")

@user'a ekle
değerler (2, "2 değer")

@user'a ekle
değerler (3, "3 değer")

@Password Tablosunu bildirin (keyValue int, ayrıntılar varchar (10))
@password içine ekle
değerler (1, '1 Şifre')
@password içine ekle
değerler (2, '2 Şifre')
@password içine ekle
değerler (3, '3 Şifre')

        --silmeden önce
  @parola'dan * seçin a iç birleşim @ kullanıcı b
                a.keyvalue = b.keyvalue üzerinde
  @user'den #deletedID'yi seçin; burada keyvalue = 1 - bu, çıktı örneği gibi çalışır
  @user'ı sil, burada keyvalue = 1
  @parola'yı sil, burada anahtar değer (#deletedid'den anahtar değeri seçin)

  --Silmeden sonra -
  @parola'dan * seçin a iç birleşim @ kullanıcı b
                a.keyvalue = b.keyvalue üzerinde


2

Hepsi belirtildi. Sadece birini kullanın DELETE ON CASCADEebeveyn üzerinde tableveya silmek child-tableiçin parent.


Alt tablodan ebeveyne silmekle ne demek istiyorsun? Soru veya yukarıda belirtilen cevaplarda gösterilene benzer birleştirme tekniğini kullanmaktan mı bahsediyorsunuz?
Imran Faruqi

1

Aaron'un daha önce belirttiği gibi, silme davranışını CASCADE olarak ayarlayabilirsiniz ve bu, bir ana kayıt silindiğinde alt kayıtları siler. Başka bir sihrin gerçekleşmesini istemediğiniz sürece (bu durumda Aaron'un cevabının 2., 3. maddeleri faydalı olacaktır), neden iç birleşimlerle silmeniz gerektiğini anlamıyorum.


0

İki tablodaki bir veri kümesini FK ilişkisiyle silmek için John Gibb'in cevabını geliştirmek için:

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

iki veya daha fazla tablodan silinmeyecek.Lütfen soruyu anlayın
Kamran Shahid

-5

$ sql = "DELETE FROM basic_tbl, education_tbl, personal_tbl, address_tbl, department_tbl KULLANARAK basic_tbl, education_tbl, personal_tbl, address_tbl, department_tbl NEREDE b_id= e_id= p_id= a_id= d_id= '" $ id.. "' "; $ r = mysqli_query ($ con $ SQL);


Lütfen biçimlendirmenizi düzeltin ve kodunuzun neden çalıştığına dair kısa bir açıklama sağlayın.
Bryan Herbst
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.