Given the schema:
What I need is having every user_identities.belongs_to
reference an users.id
.
At the same time, every users
has a primary_identity
as shown in the picture.
However when I try to add this reference with ON DELETE NO ACTION ON UPDATE NO ACTION
, MySQL says
#1452 - Cannot add or update a child row: a foreign key constraint fails (
yap
.#sql-a3b_1bf
, CONSTRAINT#sql-a3b_1bf_ibfk_1
FOREIGN KEY (belongs_to
) REFERENCESusers
(id
) ON DELETE NO ACTION ON UPDATE NO ACTION)
I suspect this is due to the circular dependency, but how could I solve it (and maintain referential integrity)?
There are a couple of options to get rid of circular dependencies. For a longer chain, A -> B -> C -> D -> A , if one of the references is removed (for instance, the D -> A reference), the cyclic reference pattern is broken, as well. For simpler patterns, such as A -> B -> A , refactoring may be necessary.
To reduce or eliminate circular dependencies, architects must implement loose component coupling and isolate failures. One approach is to use abstraction to break the dependency chain. To do this, you introduce an abstracted service interface that delivers underlying functionality without direct component coupling.
Target foreign keys normally occur in bidirectional one-to-one mappings, because one side has a foreign key and the other shares the same foreign key in the other's table.
A circular dependency occurs when two classes depend on each other. For example, class A needs class B, and class B also needs class A. Circular dependencies can arise in Nest between modules and between providers. While circular dependencies should be avoided where possible, you can't always do so.
The only way to solve this (at least with the limited capabilities of MySQL) to allow NULL
values in both FK columns. Creating a new user with a primary identity would then look something like this:
insert into users (id, primary_identity)
values (1, null);
insert into identities (id, name, belongs_to)
values (1, 'foobar', 1);
update users
set primary_identity = 1
where id = 1;
commit;
The only drawback of this solution is that you cannot force that a user has a primary identity (because the column needs to be nullable).
Another option would be to change to a DBMS that supports deferred constraints, then you can just insert the two rows and the constraint will only be checked at commit time. Or use a DBMS where you can have a partial index, then you could use the solution with an is_primary
column
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With