214

I'm trying to delete orphan entries in a mysql table.

I have 2 tables like this:

Table files:

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

table blob:

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

The fileid and id columns can be used to join the tables together.

I want to delete all rows in table blob where fileid cannot be found in the table files.id.

So using the example above that would delete rows: 3 & 4(s) in the blob table.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Martin
  • 10,294
  • 11
  • 63
  • 83

4 Answers4

421

Using LEFT JOIN/IS NULL:

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

Using NOT EXISTS:

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

Using NOT IN:

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

Warning

Whenever possible, perform DELETEs within a transaction (assuming supported - IE: Not on MyISAM) so you can use rollback to revert changes in case of problems.

Abel
  • 56,041
  • 24
  • 146
  • 247
OMG Ponies
  • 325,700
  • 82
  • 523
  • 502
  • 18
    which is, in general, the fastest of the above? – Hampus Brynolf Apr 10 '12 at 18:02
  • @HampusBrynolf: This is MySQL specific - it depends on if the columns [are nullable](http://explainextended.com/2010/05/27/left-join-is-null-vs-not-in-vs-not-exists-nullable-columns/) or [are not nullable](http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/) – OMG Ponies Apr 11 '12 at 01:57
  • 2
    For some reason, deleting using the LEFT JOIN didn't work on MS SQL Server Mgmt Studio (not sure why; it just complained about the LEFT JOIN). Anyone knows why is that? It worked using NOT EXISTS though :) – Anna May 15 '14 at 17:52
  • 11
    FYI, here's a useful discussion of the relative efficiency of these three methods: http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/ – moustachio Jun 08 '14 at 14:02
  • @OMGPonies, For the `exists` part, Why do you use `select null` instead of `select *`? Isn't it recommended to use `select *`? – Pacerier Apr 11 '15 at 14:58
  • @OMGPonies, Your answers [are wrong](http://stackoverflow.com/a/3384137/632951) because it makes the implicit assumption that the columns are `not null`. – Pacerier Apr 11 '15 at 15:18
  • What if the BLOB table is in an attached/separate DB? Thanks! – bunkerdive Apr 29 '16 at 03:13
  • As my observation, DELETE NOT IN is the slowest one, sometimes hundred times slower. NOT EXISTS and LEFT JOIN is much more faster. LEFT JOIN is a bit faster than NOT EXISTS. Of course it depends on your table structure. But generally NOT IN queries runs slower. – endo64 Jul 26 '16 at 15:39
  • 2
    @Pacerier - "wrong" is a bit strong. To make sure people understand, the answers *do* work if `fileid`is *non-nullable*. Also, the third solution (`NOT IN`) only requires that `f.id` by non-nullable. Presumably that is a primary key, so it would be. – ToolmakerSteve Sep 26 '16 at 07:42
  • 1
    In addition, the only "wrong" consequence of the first two, is that they will not delete rows of BLOB where `fileid` is null. (Actually, the first one might - to be sure, I'd have to test it.) BTW, for robust design, it should be a non-nullable field. – ToolmakerSteve Sep 26 '16 at 07:59
  • 5
    For people attempting this w/SQLite: see [this answer](http://stackoverflow.com/a/4967229/786356) – bunkerdive Oct 14 '16 at 17:06
  • For some reason the MySQL on my host server would only execute the first method. Even then, the PHPMyAdmin 4.5.1 syntax checker wouldn't accept anything between `DELETE` and `FROM`, but the query ran ok anyway when I pressed Go. – clayRay Mar 24 '20 at 07:28
  • Why is `f` needed in the 3. solution? – Ömer An Oct 01 '21 at 04:17
  • What is the difference between NOT EXISTS and NOT IN? – Biax20 May 02 '22 at 14:39
  • Found that "DELETE FROM x..." throws error and "DELETE x FROM x..." works alright. Found it here: https://stackoverflow.com/questions/2763206/deleting-rows-with-mysql-left-join – Jacobski Aug 07 '23 at 01:33
33
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...*/
      )
Martin Smith
  • 438,706
  • 87
  • 741
  • 845
21
DELETE FROM blob
WHERE NOT EXISTS (
    SELECT *
    FROM files
    WHERE id=blob.id
)
George
  • 6,006
  • 6
  • 48
  • 68
  • 1
    I think there is a `files.id` and `blob.fileid`. I'm guessing your query will result in an error. – jww Dec 20 '19 at 00:45
1
DELETE FROM <table> 
WHERE <row column you want to delete by > not in 
(select <column you want to compare other column> from <other table>)

This deletes the row when the first column doesn't appear on the second table

Royer Adames
  • 868
  • 9
  • 13