Hapus baris sql di mana ID tidak memiliki kecocokan dari tabel lain


160

Saya mencoba menghapus entri anak yatim di tabel mysql.

Saya punya 2 tabel seperti ini:

Meja files:

| id | ....
------------
| 1  | ....
| 2  | ....
| 7  | ....
| 9  | ....

meja blob:

| fileid | ....
------------
| 1  | ....
| 2  | ....
| 3  | ....
| 4  | ....
| 4  | ....
| 4  | ....
| 9  | ....

The fileiddan idkolom dapat digunakan untuk bergabung dengan tabel bersama-sama.

Saya ingin menghapus semua baris dalam tabel di blobmana fileidtidak dapat ditemukan dalam tabel files.id.

Jadi, gunakan contoh di atas yang akan menghapus baris: 3 & 4 (s) dalam blobtabel.


1
Lewati ke jawaban kedua jika Anda menggunakan nulls.
— Pacerier

Jawaban:


327

Menggunakan LEFT JOIN / IS NULL:

DELETE b FROM BLOB b 
  LEFT JOIN FILES f ON f.id = b.fileid 
      WHERE f.id IS NULL

Menggunakan BUKAN ADA:

DELETE FROM BLOB 
 WHERE NOT EXISTS(SELECT NULL
                    FROM FILES f
                   WHERE f.id = fileid)

Menggunakan TIDAK DALAM:

DELETE FROM BLOB
 WHERE fileid NOT IN (SELECT f.id 
                        FROM FILES f)

Peringatan

Kapan pun memungkinkan, lakukan DELETE dalam suatu transaksi (dengan asumsi didukung - IE: Not on MyISAM) sehingga Anda dapat menggunakan rollback untuk mengembalikan perubahan jika terjadi masalah.


12
yang mana, secara umum, yang tercepat di atas?
— Hampus Brynolf

2
Untuk beberapa alasan, menghapus menggunakan LEFT JOIN tidak berfungsi pada MS SQL Server Mgmt Studio (tidak yakin mengapa; itu hanya mengeluhkan LEFT JOIN). Adakah yang tahu kenapa begitu? Itu bekerja menggunakan TIDAK ADA :):
— Anna

5
FYI, inilah diskusi yang berguna efisiensi relatif dari ketiga metode: explainextended.com/2009/09/18/...
— Moustachio

2
@Pacerier - "salah" agak kuat. Untuk memastikan orang mengerti, jawaban melakukan pekerjaan jika fileidadalah non-nullable . Juga, solusi ketiga ( NOT IN) hanya membutuhkan f.idnon-nullable. Agaknya itu adalah kunci utama, jadi itu akan menjadi.
— ToolmakerSteve

2
Untuk orang yang mencoba ini dengan SQLite: lihat jawaban ini
— bunkerdive

26
DELETE FROM blob 
WHERE fileid NOT IN 
       (SELECT id 
        FROM files 
        WHERE id is NOT NULL/*This line is unlikely to be needed 
                               but using NOT IN...*/
      )

Apa itu "/ * Baris ini tidak mungkin diperlukan tetapi menggunakan TIDAK DI ... * /" seharusnya berarti?
— Pacerier

1
@Pacerier - NOT IN (NULL)mengembalikan set hasil kosong sehingga NULL perlu dikecualikan. Namun idkolom mungkin tidak akan dibatalkan karena itu "tidak diperlukan"
— Martin Smith

Wow tangkapan yang bagus. Jadi jawaban omgponies salah! not in(null)cukup logis, Mengapa itu tidak berhasil? Apa alasan di balik itu?
— Pacerier


1
@ Bunkerdive Kemudian gunakan tiga nama objek bagian yang menyertakan nama database.
— Martin Smith

17
DELETE FROM blob
WHERE NOT EXISTS (
    SELECT *
    FROM files
    WHERE id=blob.id
)

1
Saya pikir ada files.iddan blob.fileid. Saya menduga permintaan Anda akan menghasilkan kesalahan.
— jww

-8
delete from table1 t1 
    WHERE not exists (select id from table2 where related_field_in_t2=t1.id) 
    AND not exists (select id from table3 where related_field_in_t3=t1.id) 
    AND not exists (select id from table4 where related_field_t4=t1.id) 
    AND not exists (select id from table5 where related_field_t5=t1.id);

3
Saya telah menurunkan suara karena: 1. Ini tidak berusaha menjawab pertanyaan dalam konteks yang diposting. 2. Tidak ada penjelasan (dan jawaban hanya kode bernilai rendah di Stackoverflow). 3. NOT EXISTSsudah diposting 9 tahun yang lalu. 4. Anda belum mempromosikan praktik terbaik menggunakan huruf kapital MySQL secara konsisten. Dengan kata lain, tidak ada yang layak dipertahankan di sini - inilah sebabnya saya juga memilih untuk menghapus posting ini.
— mickmackusa
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.