Bagaimana cara menghapus dari beberapa tabel di MySQL?

116

Saya mencoba menghapus dari beberapa tabel sekaligus. Saya telah melakukan sedikit penelitian, dan menghasilkan ini

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

Namun, saya mendapatkan kesalahan ini

Uncaught Database_Exception [1064]: Anda mengalami kesalahan dalam sintaks SQL; periksa manual yang sesuai dengan versi server MySQL Anda untuk sintaks yang tepat untuk digunakan di dekat 'p,pets_activities pa ...

Saya belum pernah melakukan penghapusan tabel silang sebelumnya, jadi saya tidak berpengalaman dan terjebak untuk saat ini!

Apa yang saya lakukan salah?

alex
sumber

Jawaban:

204

Gunakan a JOINdalam DELETEpernyataan tersebut.

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

Atau Anda dapat menggunakan ...

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

... untuk menghapus hanya dari pets_activities

Lihat ini .

Untuk tunggal menghapus tabel, namun dengan integritas referensial, ada cara lain untuk melakukan dengan EXISTS, NOT EXISTS, IN, NOT INdan lain-lain Tapi yang di atas di mana Anda menentukan dari mana tabel untuk menghapus dengan alias sebelum FROMklausa dapat membuat Anda keluar dari ketat cukup beberapa melihat dengan lebih mudah. Saya cenderung menjangkau EXISTS99% kasus dan kemudian ada 1% di mana sintaks MySQL ini berlangsung sepanjang hari.

cadman
sumber
7
Saya mencoba "hapus semua dalam 1 kueri" ini dengan menggabungkan 6 tabel besar (semua orang sekitar ~ 15k baris) dan kueri tersebut membutuhkan waktu 155 detik untuk menghapus 63 baris dalam 6 tabel: O
Klemen Tušar
1
@cadman Ini adalah jawaban yang benar; mungkin ada argumen yang menentang penggunaannya, tetapi terkadang sangat berguna
Simon Christian
1
+1 Saya setuju bahwa ini adalah jawaban yang benar, karena pertanyaannya bukanlah "haruskah Anda" tetapi "bagaimana caranya". Namun, saya akan tertarik untuk mendengar tentang 1% karena saya tidak dapat memikirkan satu situasi pun di mana ini lebih disukai.
Erick Robertson
2
@techouse, apakah Anda bergabung dan memfilter indeks? 15k x 15k x 15k x 15k 15k x 15k adalah 11 juta. Apakah SELECTbutuh waktu yang sama lama?
Paul Draper
6
Anda juga dapat menggunakan LEFT JOIN, yang berguna jika tabel kedua tidak memiliki entri yang cocok, jika tidak, tidak ada yang akan dihapus.
Lexib0y
20

Karena ini tampak seperti hubungan orang tua / anak sederhana antara petsdan pets_activities, Anda akan lebih baik membuat batasan kunci asing dengan kaskade penghapusan.

Dengan begitu, saat sebuah petsbaris dihapus, pets_activitiesbaris yang terkait dengannya secara otomatis juga terhapus.

Kemudian kueri Anda menjadi sederhana:

delete from `pets`
    where `order` > :order
      and `pet_id` = :pet_id
paxdiablo
sumber
3
@Erick, asalkan Anda telah mengatur integritas referensial, penghapusan berjenjang dapat menyebabkan masalah lebih dari menghapus sendiri. Kami sudah tahu bahwa itu paadalah anak yang layak pkarena id/pet_idpemetaan.
paxdiablo
14
Nah, kalian punya pemikiran sendiri tetapi sepertinya Anda mengabaikan banyak kekuatan DBMS. Penghapusan bertingkat adalah bagian dari manajemen data seperti pemicu, prosedur tersimpan atau batasan dan mereka hanya berbahaya jika Anda tidak tahu apa yang Anda lakukan. Namun, saya tidak akan memperdebatkan hal tersebut lebih lanjut, kita hanya harus setuju untuk tidak setuju.
paxdiablo
8
Erick, sekarang kamu menarik minat saya. Bagaimana Anda memastikan integritas data dalam database tanpa kendala?
paxdiablo
4
@Erick berkata, "Saya juga tidak menggunakan pemicu, prosedur tersimpan, atau batasan." Ah, Anda menggunakan Excel. :-)
james.garriss
4
Saya hanya ingin menindaklanjuti ini. Saya telah mengubah posisi saya untuk menghapus kaskade dalam situasi ini. Saya telah menjadi bagian dari lingkungan SQL baru yang menggunakannya, dan menggunakannya dengan baik dan sangat terorganisir. Dalam sistem ini, kami bekerja dengan sangat baik untuk keuntungan kami untuk menerapkan kaskade ini. Ini tentu mencegah data yatim piatu dan tidak berbahaya. Masalahnya adalah setiap orang yang bekerja dengan database perlu memahami cara menggunakannya dengan aman. Namun selalu ada risiko saat developer junior membuat perubahan database tanpa pengawasan.
Erick Robertson
14

Gunakan ini

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

atau

DELETE `articles`, `comments` 
FROM `articles`, `comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4
RN Kushwaha
sumber
1
Menemukan referensi yang bagus untuk menggunakan ini dan beberapa opsi lain di mysqltutorial.org/mysql-delete-statement.aspx
Mavelo
3

Saya tidak memiliki database mysql untuk diuji saat ini, tetapi apakah Anda sudah mencoba menentukan apa yang harus dihapus sebelum klausa from? Sebagai contoh:

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`

Saya pikir sintaks yang Anda gunakan terbatas pada versi mysql yang lebih baru.

Brandon Horsley
sumber
1
Kueri itu berhasil dieksekusi, namun, tidak menghapus baris apa pun (tetapi saya yakin seharusnya ada).
alex
2

Bagi saya sintaksnya terlihat benar ... coba ubah untuk digunakan INNER JOIN ...

Coba lihat ini .

Andre Gallo
sumber
7
Sayang sekali Anda tidak menyertakan solusi sebenarnya, karena tautannya benar!
mycroes
1

Kepada siapa pun yang membaca ini di tahun 2017, beginilah cara saya melakukan sesuatu yang serupa.

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

Secara umum, untuk menghapus baris dari beberapa tabel, sintaks yang saya ikuti diberikan di bawah ini. Solusi ini didasarkan pada asumsi bahwa ada hubungan antara kedua tabel.

DELETE table1, table2 FROM table1 inner join table2 on table2.id = table1.id
WHERE [conditions]
Kalesh Kaladharan
sumber
1

Saya menemukan artikel ini yang menunjukkan kepada Anda cara menghapus data dari beberapa tabel dengan menggunakan pernyataan MySQL DELETE JOIN dengan penjelasan yang baik.

masukkan deskripsi gambar di sini

Ravi Makwana
sumber