Question

So I have two tables:

  1. Bookmarks has a few columns [id, etc.]
  2. Person_Bookmark has 2 columns [personId, bookmarkId]

Bookmarks represents links to other websites. All valid bookmarks have an id. The Person_Bookmark table has a bunch of personIds and their bookmarks, shown as bookmarkId.

Here's my pseudocode:

> let x = integer list of all bookmarkId's from Person_Bookmark
> 
> for each x  {   
>     if ('select * from 'Bookmarks' where 'id' = x returns 0 rows) {
>       delete from 'person_bookmark' where 'bookmarkId' = x
>     }
> }

Please advise me how to convert to a Postgres [edit] SQL script.

Was it helpful?

Solution

@Jan mentioned foreign keys already, but his advice is incomplete.

Seems like you want to delete all associations to a bookmark that does not exist (any more).
Define a foreign key constraint in the form of:

ALTER TABLE person_bookmarks
ADD CONSTRAINT pb_fk FOREIGN KEY (bookmarkid) REFERENCES bookmarks (id)
ON UPDATE CASCADE
ON DELETE CASCADE;
  • This only allows values in person_bookmarks.bookmarkid that exist in bookmarks.id.

  • ON UPDATE CASCADE changes corresponding values in person_bookmarks.bookmarkid when you change an entry in bookmarks.id

  • ON DELETE CASCADE deletes corresponding rows in person_bookmarks.bookmarkid when you change an entry in bookmarks.id.

Other options are available, read the manual.

The ON DELETE CASCADE clause does automatically, what you are trying to fix manually. Before you can add the fk constraint you'll have to fix it manually once:

DELETE FROM person_bookmarks pb
WHERE NOT EXISTS (SELECT 1 FROM bookmarks b WHERE b.id = pb.bookmarkid);
-- OR NOT EXISTS (SELECT 1 FROM persons p   WHERE p.id = pb.personid);

Deletes all rows with non-existing bookmarkid. Uncomment the last line to get rid of dead persons, too.

OTHER TIPS

This works in SQL Server - not sure about MySQL...

delete pb
from
  person_bookmark pb
where not exists (select 1 from booksmarks b where b.id = pb.bookmarkid)

Another version of @Derek's reply:

DELETE FROM person_bookmark 
WHERE bookmarkid NOT IN (SELECT id FROM bookmarks)

The need to do this implies that you have no foreign key indexes between your tables. I strongly advise you to do so. The drawback (or feature) lies in that when you for example delete a person (I'm guessing this table exists from your example), you have to delete all associated data first, otherwise the server will throw an error.

Something like this:

DELETE FROM person_Bookmark WHERE personid = @personid
DELETE FROM person_SomeOtherTable WHERE personid = @personid
DELETE FROM person WHERE id = @personid

The advantage though is that you'll have no orphan rows in your database, and you can't enter erroneous data by mistake (store a bookmark for a person that doesn't exist).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top