I have a problem with mutual constraints.
I want to have two tables each having a constraint on the other one.
I’m working with Doctrine2 (but it’s not related to the problem), here is my simplified code:
SQL:
CREATE TABLE IF NOT EXISTS `thread` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`last_message_id` int(11) DEFAULT NULL,
`subject` varchar(255) NOT NULL
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_C023F2BBBA0E79C3` (`last_message_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `thread`
ADD CONSTRAINT `FK_C023F2BBBA0E79C3` FOREIGN KEY (`last_message_id`) REFERENCES `message` (`id`);
CREATE TABLE IF NOT EXISTS `message` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`thread_id` int(11) DEFAULT NULL,
`body` longtext NOT NULL
PRIMARY KEY (`id`),
KEY `IDX_9E4E8B5FA76ED395` (`user_id`),
KEY `IDX_9E4E8B5FE2904019` (`thread_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `message`
ADD CONSTRAINT `FK_9E4E8B5FE2904019` FOREIGN KEY (`thread_id`) REFERENCES `thread` (`id`) ON DELETE CASCADE;
Doctrine2 mapping (which generated the SQL code above):
<?php
class Thread
{
/* @ORM\OneToOne() */
private $lastMessage;
}
class Message
{
/* @ORM\ManyToOne() */
private $thread;
}
And when I try to delete either a thread or a message, I get (logically) the error:
Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails ('thread', CONSTRAINT 'FK_C023F2BBBA0E79C3' FOREIGN KEY ('last_message_id') REFERENCES 'message' ('id'))
So, is there a way to avoid this error?
Or should I forget mutual constraints?
Anything?
I want to add that I want to keep the last_message_id because I want to display the threads with infos on their last message, and making a (paginated) query without this reference to the last message was a total nightmare…
Thanks!
The best solution I can think of would be to add a
ON DELETE CASCADEconstraint to the FK on the Thread table. That way if you delete the thread, the associated messages would be automatically deleted as well.Similarly, you would need to add a
ON DELETE SET NULLconstraint on the Messages table FK so that if you deleted the last message in a Thread, it would set the last_message_id to NULL on the Thread table.Or you could just do logical (soft) deletes instead of hard deletes, which would also solve the problem.
ETA:
Now that you’ve posted the constraints, this is the one you would have to modify: