Usuń wiersze sql, w przypadku których identyfikatory nie pasują do innej tabeli


160

Próbuję usunąć osierocone wpisy w tabeli mysql.

Mam 2 takie tabele:

Tabela files:

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

stół blob:

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

Do łączenia tabel można użyć kolumn fileidi id.

Chcę usunąć wszystkie wiersze w tabeli, blobktórych fileidnie można znaleźć w tabeli files.id.

Korzystając z powyższego przykładu, można usunąć wiersze: 3 i 4 (y) w blobtabeli.


1
Przejdź do drugiej odpowiedzi, jeśli używasz nulls.
— Pacerier,

Odpowiedzi:


327

Używanie LEFT JOIN / IS NULL:

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

Korzystanie NIE ISTNIEJE:

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

Korzystanie NOT IN:

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

Ostrzeżenie

O ile to możliwe, wykonaj DELETE w ramach transakcji (zakładając, że jest obsługiwana - IE: nie w MyISAM), aby móc użyć wycofywania zmian w celu cofnięcia zmian w przypadku problemów.


12
który jest na ogół najszybszy z powyższych?
— Hampus Brynolf

2
Z jakiegoś powodu usuwanie za pomocą LEFT JOIN nie działało na MS SQL Server Mgmt Studio (nie wiem dlaczego; po prostu narzekał na LEFT JOIN). Czy ktoś wie, dlaczego tak jest? Zadziałało przy użyciu NIE ISTNIEJE :)
— Anna

5
Do Twojej wiadomości, oto pożyteczna dyskusja na temat względnej skuteczności tych trzech metod: wyjaśnieniextended.com
— 09/18/ ...

2
@Pacerier - „źle” jest trochę mocne. Aby upewnić się, że ludzie rozumieją, odpowiedzi wykonać pracę, jeśli fileidjest bez pustych . Ponadto trzecie rozwiązanie ( NOT IN) wymaga tylko tego, aby f.idnie dopuszczać wartości null. Przypuszczalnie jest to klucz podstawowy, więc tak by było.
— ToolmakerSteve

2
Dla osób próbujących tego w / SQLite: zobacz tę odpowiedź
— 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...*/
      )

Co to jest „/ * Ta linia prawdopodobnie nie będzie potrzebna, ale użycie NOT IN ... * /” powinno oznaczać?
— Pacerier,

1
@Pacerier - NOT IN (NULL)zwraca pusty zestaw wyników, więc należy wykluczyć wartości NULL. Ale idkolumna prawdopodobnie i tak nie będzie miała wartości null, stąd „raczej nie będzie potrzebna”
— Martin Smith

Wow, dobry chwyt. Więc odpowiedź omgponies jest błędna! not in(null)jest całkiem logiczne, dlaczego nie działa? Jaki jest tego powód?
— Pacerier,


1
@bunkerdive Następnie użyj trzyczęściowych nazw obiektów, które zawierają nazwę bazy danych.
— Martin Smith

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

1
Myślę, że jest files.idi blob.fileid. Zgaduję, że twoje zapytanie spowoduje błąd.
— 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
Oddałem głos, ponieważ: 1. To nie jest próbą odpowiedzi na pytanie w kontekście, który został opublikowany. 2. Nie ma żadnego wyjaśnienia (a odpowiedzi zawierające tylko kod mają niską wartość w Stackoverflow). 3. NOT EXISTSzostał opublikowany już 9 lat temu. 4. Nie promowałeś najlepszej praktyki polegającej na konsekwentnym używaniu wielkich liter w słowach kluczowych MySQL. Innymi słowy, nie ma tu nic wartego zachowania - dlatego też głosowałem za usunięciem tego posta.
— mickmackusa
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.