Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove rows NOT referenced by a foreign key

Tags:

sql

postgresql

This is somewhat related to this question:

I have a table with a primary key, and I have several tables that reference that primary key (using foreign keys). I need to remove rows from that table, where the primary key isn't being referenced in any of those other tables (as well as a few other constraints).

For example:

Group
groupid | groupname
    1   |    'group 1'
    2   |    'group 3'
    3   |    'group 2'
    ... |    '...'

Table1
tableid | groupid | data
    1   |    3    |    ...
    ... |    ...  |    ...

Table2
tableid | groupid | data
    1   |    2    |    ...
    ... |    ...  |    ...

and so on. Some of the rows in Group aren't referenced in any of the tables, and I need to remove those rows. In addition to this, I need to know how to find all of the tables/rows that reference a given row in Group.

I know that I can just query every table and check the groupid's, but since they are foreign keys, I imagine that there is a better way of doing it.

This is using Postgresql 8.3 by the way.

like image 578
Niki Yoshiuchi Avatar asked Aug 18 '09 16:08

Niki Yoshiuchi


People also ask

How do you delete a table that has a foreign key reference?

To delete a foreign key constraintIn Object Explorer, expand the table with the constraint and then expand Keys. Right-click the constraint and then click Delete. In the Delete Object dialog box, click OK.

Can delete work without WHERE clause?

Example - DELETE Statement with One ConditionIf you run a DELETE statement with no conditions in the WHERE clause, all of the records from the table will be deleted. As a result, you will most often include a WHERE clause with at least one condition in your DELETE statement.


2 Answers

DELETE
FROM    group g
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    table1 t1
        WHERE   t1.groupid = g.groupid
        UNION ALL
        SELECT  NULL
        FROM    table1 t2
        WHERE   t2.groupid = g.groupid
        UNION ALL
        …
        )
like image 162
Quassnoi Avatar answered Sep 28 '22 03:09

Quassnoi


At the heart of it, SQL servers don't maintain 2-way info for constraints, so your only option is to do what the server would do internally if you were to delete the row: check every other table.

If (and be damn sure first) your constraints are simple checks and don't carry any "on delete cascade" type statements, you can attempt to delete everything from your group table. Any row that does delete would thus have nothing reference it. Otherwise, you're stuck with Quassnoi's answer.

like image 39
Jeff Ferland Avatar answered Sep 28 '22 03:09

Jeff Ferland