Why in MySQL, INSERT IGNORE INTO
does not change the foreign key constraint errors into warnings?
I'm trying to insert a number of records into a table and I expect MySQL to leave out the ones that result in error, any error, and insert the rest. Does anyone have any suggestions?
And the SET FOREIGN_KEY_CHECKS = 0;
is not my answer. Because I expect the rows which defy the constraints not to be inserted at all.
Thanks
INSERT IGNORE is just a workaround for the lazy. You shouldn't be inserting duplicates records in the first place. Besides a Primary/Unique is not the same as a Foreign key. And have in mind that IGNORE will also ignore other error and warnings (division by zero, data truncations), which usually is not a good thing.
In this case, and almost every time, it makes more sense to use REPLACE instead of INSERT IGNORE. Another option is ON DUPLICATE KEY UPDATE.
In your case, if you can't remove the missing parents before the insert, you can manage the same thing with a temporary table like this:
Regards, Jose.
[NEW ANSWER]
Thanks to @NeverEndingQueue for bringing this up. It seems MySQL has finally fixed this issue. I'm not sure which version this problem was first fixed in, but right now I tested with the following version and the problem is not there anymore:
To be clear:
To better understand the meaning of this last query and why it shows the problem is fixed, please continue with the old answer below.
[OLD ANSWER]
My solution is a work around to the problem and the actual solution will always be fixing the problem within the MySQL itself.
The following steps solved my problem:
a. Consider having the following tables and data:
b. Now we need to delete some of the rows to demonstrate the problem:
c. PROBLEM: The problem arises when you try to insert the following child rows:
Even though the
IGNORE
keyword is used, but MySQL cancels the the requested operation because the generated error is not turned into warning (as it supposed to). Now that the problem is obvious, let's see how can we execute the last insert into statement without facing any error.d. SOLUTION: I'm going to wrap the insert into statement by some other constant statements which are neither dependent on the records inserted, nor on their number.
I know that this is not optimum but as long as MySQL has not fixed the problem, this is the best I know. Especially since all the statements can be executed in one request if you use mysqli library in PHP.
I believe
INSERT IGNORE
is intended to ignore errors from the server layer, not the storage engine layer. So it will help for duplicate key errors (it's primary use case) and certain data conversions, but not foreign key errors, which come from the storage engine layer.As for your specific requirement:
For that I recommend using
mysql -f
to force it to keep running despite any errors. So for example, if you have a file like this:Then you can load that file like so, which will insert the good rows and ignore the error from the bad rows:
If you are inserting a row into the database, you can run this check explicitly using an additional query. Say you have these tables:
and you want to insert a new user (George, who has pet #1). You could do something like
Please excuse the overly simplified code and bad practices in my example -- it's just meant as illustrative of a possible work-around.
This issue seems to be fixed in MySQL 5.7, see https://bugs.mysql.com/bug.php?id=78853.
Now foreign key constraint error is turned into warning instead:
I think the simplest, mysql solution to the problem is joining into the foreign key table to verify constraints:
But it seems strange that you want to throw away records based on missing foreign keys. I, for instance, prefer having INSERT IGNORE error on foreign key checks.