MySQL'de birden çok tablodan nasıl silinir?


117

Aynı anda birkaç tablodan silmeye çalışıyorum. Biraz araştırma yaptım ve bunu buldum

DELETE FROM `pets` p,
            `pets_activities` pa
      WHERE p.`order` > :order
        AND p.`pet_id` = :pet_id
        AND pa.`id` = p.`pet_id`

Ancak bu hatayı alıyorum

Yakalanmamış Database_Exception [1064]: SQL sözdiziminizde bir hata var; "p, pets_activitiespa " yakınında kullanılacak doğru sözdizimi için MySQL sunucu sürümünüze karşılık gelen kılavuza bakın .

Daha önce hiç çapraz tablo silme işlemi yapmadım, bu yüzden deneyimsizim ve şimdilik sıkıştım!

Neyi yanlış yapıyorum?

Yanıtlar:


205

Bir kullan JOINiçinde DELETEdeyimi.

DELETE p, pa
      FROM pets p
      JOIN pets_activities pa ON pa.id = p.pet_id
     WHERE p.order > :order
       AND p.pet_id = :pet_id

Alternatif olarak kullanabilirsiniz ...

DELETE pa
      FROM pets_activities pa
      JOIN pets p ON pa.id = p.pet_id
 WHERE p.order > :order
   AND p.pet_id = :pet_id

... sadece şuradan silmek için pets_activities

Bunu gör .

Tek tablo siler için henüz başvuru bütünlüğü ile, diğer yapmanın yolu vardır EXISTS, NOT EXISTS, IN, NOT INvb Ama önce bir takma ad ile silmek için hangi tabloları gelen belirtmek nereye yukarıda bir FROMfıkra birkaç güzel Sımsıkı ait çıkarabilirim daha kolay lekeler. EXISTSVakaların% 99'una ulaşma eğilimindeyim ve sonra bu MySQL sözdiziminin günü aldığı% 1 var.


7
Bu "hepsini bir arada sil" sorgusunu 6 büyük tabloyu birleştirerek denedim (herkes yaklaşık 15 bin satır) ve sorgunun 6 tablodaki 63 satırı silmesi 155 saniye sürdü: O
Klemen Tušar

1
@cadman Bu gerçek doğru cevap; kullanımına karşı argümanlar olabilir, ancak ara sıra çok yararlıdır
Simon Christian

1
+1 Soru "yapmalısın" değil, "nasıl yapılır" olduğu için, bunun gerçek doğru cevapta olduğunu kabul ediyorum. Bununla birlikte,% 1'i duymakla ilgilenirim çünkü bunun tercih edileceği tek bir durum düşünemiyorum.
Erick Robertson

2
@techouse, endekslere katılıp filtrelendiniz mi? 15k x 15k x 15k x 15k 15k x 15k, 11 milyondur. SELECTBenzer şekilde uzun sürdü mü ?
Paul Draper

6
Ayrıca, ikinci tabloda eşleşen girişler yoksa yararlı olan LEFT JOIN'i de kullanabilirsiniz, aksi takdirde hiçbir şey silinmez.
Lexib0y

20

Bu , petsve arasında basit bir ebeveyn / çocuk ilişkisi gibi göründüğünden pets_activities, yabancı anahtar kısıtlamanızı silme kademesiyle oluşturmanız daha iyi olur.

Bu şekilde, bir petssatır silindiğinde, pets_activitiesonunla ilişkili satırlar da otomatik olarak silinir.

Ardından sorgunuz basitleşir:

delete from `pets`
    where `order` > :order
      and `pet_id` = :pet_id

3
@Erick, bilgi tutarlılığını ayarladıysanız, kademeli silme işlemleri kendi başına silmekten daha fazla soruna neden olamaz. Bunun haritalama nedeniyle pauygun bir çocuk olduğunu zaten biliyoruz . pid/pet_id
paxdiablo

14
Pekala, kendi düşünceleriniz var ama görünüşe göre DBMS'nin gücünün çoğunu küçümsüyorsunuz '. Basamaklı silme işlemleri, tetikleyiciler, depolanmış prosedürler veya kısıtlamalar kadar veri yönetiminin bir parçasıdır ve yalnızca ne yaptığınızı bilmiyorsanız tehlikelidir. Yine de konuyu daha fazla tartışmayacağım, sadece aynı fikirde olmadığımızı kabul etmemiz gerekecek.
paxdiablo

8
Erick, şimdi ilgimi çektin. Veri bütünlüğünü kısıtlamalar olmadan veritabanında nasıl sağlarsınız?
paxdiablo

4
@Erick, "Tetikleyiciler, saklanan prosedürler veya kısıtlamalar da kullanmıyorum" dedi. Ah, Excel kullanıyorsun. :-)
james.garriss

4
Sadece bunu takip etmek istiyorum. Bu durumda basamakları silme konusundaki pozisyonumu değiştirdim. Onları kullanan, iyi kullanan yeni bir SQL ortamının parçası oldum ve çok düzenliydiler. Bu sistemde, bu kademelerin yerinde olması bizim yararımıza çok iyi çalıştı. Kesinlikle öksüz verileri engelledi ve tehlikeli değildi. Sorun, veritabanıyla çalışan herkesin bunları güvenli bir şekilde nasıl kullanacağını anlaması gerektiğidir. Ancak, küçük geliştiriciler denetimsiz olarak veritabanı değişiklikleri yaptığında her zaman riskler vardır.
Erick Robertson

14

Bunu kullan

DELETE FROM `articles`, `comments` 
USING `articles`,`comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4

veya

DELETE `articles`, `comments` 
FROM `articles`, `comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4


3

Şu anda üzerinde test edebileceğim bir mysql veritabanım yok, ancak from cümlesinden önce neyin silineceğini belirlemeyi denediniz mi? Örneğin:

DELETE p, pa FROM `pets` p,
        `pets_activities` pa
  WHERE p.`order` > :order
    AND p.`pet_id` = :pet_id
    AND pa.`id` = p.`pet_id`

Kullandığınız sözdiziminin mysql'nin daha yeni sürümleriyle sınırlı olduğunu düşünüyorum.


1
Bu sorgu başarıyla yürütüldü, ancak herhangi bir satırı silmedi (ancak olması gerektiğine inanıyorum).
alex

2

Sözdizimi bana doğru görünüyor ... kullanmak için değiştirmeye çalışın INNER JOIN...

Göz at bu .


7
Bağlantının doğru olması nedeniyle asıl çözümü eklememeniz çok kötü!
mycroes

1

2017'de bunu okuyan herkese, ben de benzer bir şey yaptım.

DELETE pets, pets_activities FROM pets inner join pets_activities
on pets_activities.id = pets.id WHERE pets.`order` > :order AND 
pets.`pet_id` = :pet_id

Genel olarak, birden çok tablodan satır silmek için takip ettiğim sözdizimi aşağıda verilmiştir. Çözüm, iki tablo arasında bir miktar ilişki olduğu varsayımına dayanmaktadır.

DELETE table1, table2 FROM table1 inner join table2 on table2.id = table1.id
WHERE [conditions]

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.