Skip to content
Advertisement

MySQL (Percona) Error 1452: Cannot add or update a child row for no reason

I have 2 Database Tables “users” and “tasks”. The tasks table contains two foreign keys for the createdBy_user_id and updatedBy_user_id columns both referencing users.id. If I try to insert an entry to tasks (after making sure the user referenced by the foreign keys exists) like this:

The query fails with Error 1452:

I don’t know why this happens, because everything works fine if I remove the constraint. The same error does not happen for the “updatedBy_user_id” column making this such confusing.

The Tables have the following DDL:

Users table:

Tasks table:

As you can see the datatypes match and both tables use the InnoDB Engine. The users table contains one entry:

So there is no obvious reason, why the insertion should fail. Have you an idea what’s wrong with my tables? Looks like a software bug.

Advertisement

Answer

This is a bug. MySQL 5.7 has had some troubles with generated columns and foreign keys, and I assume this is an unfixed variant of Bug #79772 Foreign key not allowed when a virtual index exists.

In your particular case, and probably depending on your exact version, any of the following modifications seems to prevent that bug from occurring:

  • do not use a virtual column, but make it stored
  • do not create a foreign key for a column directly following the virtual column, so e.g. change the column order to year, status, createdBy_user_id, updatedBy_user_id.
  • do not use a unique index on the virtual column, a normal index should be fine (at least in a version where the linked bug is fixed). You want a unique constraint, so this is not an option, but the fact that this fixes your problem emphasized the “bug” nature of the problem.

The second bullet point seems to be the underlying bug: I assume that some iterator doesn’t count the virtual column properly, so the foreign key that shall check createdBy_user_id seems to mix up the columns and actually checks the value of year (in this case “20”) against the users table. So if you have a user with id “20” in your users table, the foreign key will actually accept this, no matter what value for createdBy_user_id you are trying to insert, see the MySQL 5.7.29 fiddle.

Unless you have a specific reason to use a virtual column, using stored is probably the sane thing to do.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement