Can it be done "automatically" or do I have to check every time I
delete one row from users_cards this?
Depends what you mean on automatically.
I would use triggers:
DELIMITER $$
CREATE DEFINER=CURRENT_USER TRIGGER `name_of_this_trigger`
AFTER DELETE ON `users_cards` FOR EACH ROW
BEGIN
DELETE FROM `cards` WHERE `id` NOT IN (SELECT DISTINCT `card_id` FROM `users_cards`);
END $$
DELIMITER ;
If you execute it on your database, it will add a trigger which runs and checks for user-less cards, and delete them without any additional hassle after each DELETE query on the users_cards
table.
However, it will not run, thus failing to delete any potentially user-less cards, if a users_cards
has been deleted by a cascade event.
So, you can do two things. Nothing: the garbage will be cleaned up on the next DELETE query on users_cards
anyhow. Or; You can add another trigger, which runs after a DELETE query on the users
table like so (to delete any potential cards which now doesn't have a users_cards
due to a cascading DELETE originating from users
):
DELIMITER $$
CREATE DEFINER=CURRENT_USER TRIGGER `name_this_very_trigger`
AFTER DELETE ON `users` FOR EACH ROW
BEGIN
DELETE FROM `cards` WHERE `id` NOT IN (SELECT DISTINCT `card_id` FROM `users_cards`);
END $$
DELIMITER ;
FYI: If you noticed, there is only one statement after the trigger declaration, so you don't even need the BEGIN ... END
block, which means that the DELIMITER
nonsense is needless as well.
Let me know if it helped!
ps.: And for God's sake; Please don't use plural table names. You are naming the entities stored in the table not the table itself.