I'm having a bit of a strange problem. I'm trying to add a foreign key to one table that references another, but it is failing for some reason. With my limited knowledge of MySQL, the only thing that could possibly be suspect is that there is a foreign key on a different table referencing the one I am trying to reference.
I've done a SHOW CREATE TABLE query on both tables, sourcecodes_tags is the table with the foreign key, sourcecodes is the referenced table.
CREATE TABLE `sourcecodes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) unsigned NOT NULL,
`language_id` int(11) unsigned NOT NULL,
`category_id` int(11) unsigned NOT NULL,
`title` varchar(40) CHARACTER SET utf8 NOT NULL,
`description` text CHARACTER SET utf8 NOT NULL,
`views` int(11) unsigned NOT NULL,
`downloads` int(11) unsigned NOT NULL,
`time_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `language_id` (`language_id`),
KEY `category_id` (`category_id`),
CONSTRAINT `sourcecodes_ibfk_3` FOREIGN KEY (`language_id`) REFERENCES `languages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `sourcecodes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `sourcecodes_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `sourcecodes_tags` (
`sourcecode_id` int(11) unsigned NOT NULL,
`tag_id` int(11) unsigned NOT NULL,
KEY `sourcecode_id` (`sourcecode_id`),
KEY `tag_id` (`tag_id`),
CONSTRAINT `sourcecodes_tags_ibfk_1` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
This is the code that generates the error:
ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE
Quite likely your sourcecodes_tags table contains sourcecode_id values that no longer exists in your sourcecodes table. You have to get rid of those first.
Here's a query that can find those IDs:
SELECT DISTINCT sourcecode_id FROM
sourcecodes_tags tags LEFT JOIN sourcecodes sc ON tags.sourcecode_id=sc.id
WHERE sc.id IS NULL;
I had the same issue with my MySQL database but finally, I got a solution which worked for me.
Since in my table everything was fine from the mysql point of view(both tables should use InnoDB engine and the datatype of each column should be of the same type which takes part in foreign key constraint).
The only thing that I did was to disable the foreign key check and later on enabled it after performing the foreign key operation.
Steps that I took:
SET foreign_key_checks = 0;
alter table tblUsedDestination add constraint f_operatorId foreign key(iOperatorId) references tblOperators (iOperatorId); Query
OK, 8 rows affected (0.23 sec) Records: 8 Duplicates: 0 Warnings: 0
SET foreign_key_checks = 1;
Use NOT IN to find where constraints are constraining:
SELECT column FROM table WHERE column NOT IN
(SELECT intended_foreign_key FROM another_table)
so, more specifically:
SELECT sourcecode_id FROM sourcecodes_tags WHERE sourcecode_id NOT IN
(SELECT id FROM sourcecodes)
EDIT: IN and NOT IN operators are known to be much faster than the JOIN operators, as well as much easier to construct, and repeat.
Truncate the tables and then try adding the FK Constraint.
I know this solution is a bit awkward but it does work 100%. But I agree that this is not an ideal solution to deal with problem, but I hope it helps.
For me, this problem was a little different and super easy to check and solve.
You must ensure BOTH of your tables are InnoDB. If one of the tables, namely the reference table is a MyISAM, the constraint will fail.
SHOW TABLE STATUS WHERE Name = 't1';
ALTER TABLE t1 ENGINE=InnoDB;
This also happens when setting a foreign key to parent.id to child.column if the child.column has a value of 0 already and no parent.id value is 0
You would need to ensure that each child.column is NULL or has value that exists in parent.id
And now that I read the statement nos wrote, that's what he is validating.
I had the same problem today. I tested for four things, some of them already mentioned here:
Are there any values in your child column that don't exist in the parent column (besides NULL, if the child column is nullable)
Do child and parent columns have the same datatype?
Is there an index on the parent column you are referencing? MySQL seems to require this for performance reasons (http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html)
And this one solved it for me: Do both tables have identical collation?
I had one table in UTF-8 and the other in iso-something. That didn't work. After changing the iso-table to UTF-8 collation the constraints could be added without problems. In my case, phpMyAdmin didn't even show the child table in iso-encoding in the dropdown for creating the foreign key constraint.
It seems there is some invalid value for the column line 0 that is not a valid foreign key so MySQL cannot set a foreign key constraint for it.
You can follow these steps:
Drop the column which you have tried to set FK constraint for.
Add it again and set its default value as NULL.
Try to set a foreign key constraint for it again.
I'd the same problem, I checked rows of my tables and found there was some incompatibility with the value of fields that I wanted to define a foreign key. I corrected those value, tried again and the problem was solved.
I end up delete all the data in my table, and run alter again. It works. Not the brilliant one, but it save a lot time, especially your application is still in development stage without any customer data.
try this
SET foreign_key_checks = 0;
ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE
SET foreign_key_checks = 1;
I had this exact same problem about three different times. In each instance it was because one (or more) of my records did not conform to the new foreign key. You may want to update your existing records to follow the syntax constraints of the foreign key before trying to add the key itself. The following example should generally isolate the problem records:
SELECT * FROM (tablename)
WHERE (candidate key) <> (proposed foreign key value)
AND (candidate key) <> (next proposed foreign key value)
repeat AND (candidate key) <> (next proposed foreign key value) within your query for each value in the foreign key.
If you have a ton of records this can be difficult, but if your table is reasonably small it shouldn't take too long. I'm not super amazing in SQL syntax, but this has always isolated the issue for me.
Empty both your tables' data and run the command. It will work.
I was getting this error when using Laravel and eloquent, trying to make a foreign key link would cause a 1452. The problem was lack of data in the linked table.
Please see here for an example: http://mstd.eu/index.php/2016/12/02/laravel-eloquent-integrity-constraint-violation-1452-foreign-key-constraint/
You just need to answer one question:
Is your table already storing data? (Especially the table included foreign key.)
If the answer is yes, then the only thing you need to do is to delete all the records, then you are free to add any foreign key to your table.
Delete instruction: From child(which include foreign key table) to parent table.
The reason you cannot add in foreign key after data entries is due to the table inconsistency, how are you going to deal with a new foreign key on the former data-filled the table?
If the answer is no, then follow other instructions.
I was readying this solutions and this example may help.
My database have two tables (email and credit_card) with primary keys for their IDs. Another table (client) refers to this tables IDs as foreign keys. I have a reason to have the email apart from the client data.
First I insert the row data for the referenced tables (email, credit_card) then you get the ID for each, those IDs are needed in the third table (client).
If you don't insert first the rows in the referenced tables, MySQL wont be able to make the correspondences when you insert a new row in the third table that reference the foreign keys.
If you first insert the referenced rows for the referenced tables, then the row that refers to foreign keys, no error occurs.
Hope this helps.
Make sure the value is in the other table otherwise you will get this error, in the assigned corresponding column.
So if it is assigned column is assigned to a row id of another table , make sure there is a row that is in the table otherwise this error will appear.
you can try this exapmple
START TRANSACTION;
SET foreign_key_checks = 0;
ALTER TABLE `job_definers` ADD CONSTRAINT `job_cities_foreign` FOREIGN KEY
(`job_cities`) REFERENCES `drop_down_lists`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
SET foreign_key_checks = 1;
COMMIT;
Note : if you are using phpmyadmin just uncheck Enable foreign key checks
as example
hope this soloution fix your problem :)
UPDATE sourcecodes_tags
SET sourcecode_id = NULL
WHERE sourcecode_id NOT IN (
SELECT id FROM sourcecodes);
should help to get rid of those IDs. Or if null is not allowed in sourcecode_id, then remove those rows or add those missing values to the sourcecodes table.
I had the same problem and found solution, placing NULL instead of NOT NULL on foreign key column. Here is a query:
ALTER TABLE `db`.`table1`
ADD COLUMN `col_table2_fk` INT UNSIGNED NULL,
ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC),
ADD CONSTRAINT `col_table2_fk1`
FOREIGN KEY (`col_table2_fk`)
REFERENCES `db`.`table2` (`table2_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
MySQL has executed this query!
In my case, I created a new table with the same structure, created the relationships with the other tables, then extracted the data in CSV from the old table that has the problem, then imported the CSV to the new table and disabled foreign key checking and disabled import interruption, all my data are inserted to the new table that has no problem successfully, then deleted the old table.
It worked for me.
I have a MySQL table whose definition is as follows:
CREATE TABLE `guestbook` (
`Id` int(10) unsigned NOT NULL,
`ThreadId` int(10) unsigned NOT NULL,
PRIMARY KEY (`Id`),
KEY `ThreadId` (`ThreadId`),
CONSTRAINT `guestbook_ibfk_1` FOREIGN KEY (`ThreadId`) REFERENCES `guestbook` (`Id`)
) ENGINE=InnoDB;
and currently there's only 1 row in the table:
mysql> select * from guestbook;
+-----+----------+
| Id | ThreadId |
+-----+----------+
| 211 | 211 |
+-----+----------+
The problem is that there's no way to delete this row without breaking the constraint.
mysql> delete from guestBook;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`polaris`.`guestbook`, CONSTRAINT `guestbook_ibfk_1` FOREIGN KEY (`ThreadId`) REFERENCES `guestbook` (`Id`))
As the ThreadId column was defined not null, it is also impossible to set the ThreadId to a different value temporarily to delete the row. Is there a way to delete the row without changing the definition of the table or dropping the entire table?
You can temporarily disable foreign key constraints with this query:
SET foreign_key_checks = 0;
If you put an ON DELETE CASCADE action on your foreign key, you should be able to delete rows that are self-referencing.
CONSTRAINT `guestbook_ibfk_1` FOREIGN KEY (`ThreadId`) REFERENCES `guestbook` (`Id`) ON DELETE CASCADE
The benefit this has over using ON DELETE SET NULL is that you don't have to alter your schema to make the "ThreadId" column nullable.
There are several workarounds. The approach suggested by others ...
SET foreign_key_checks = 0;
... will disable the foreign keys of every table. This is not suitable for use in a shared environment.
Another approach is to drop the foreign key using
ALTER TABLE `guestbook`
DROP FOREIGN KEY `guestbook_ibfk_1`
/
We can sort out the data using DML, and then reinstate the foreign key using:
ALTER TABLE `guestbook`
ADD CONSTRAINT `guestbook_ibfk_1` FOREIGN KEY (`ThreadId`)
REFERENCES `guestbook` (`Id`)
/
But is there a way to change the data without executing any DDL? Well, we can insert a new record and change the current record to reference it:
INSERT INTO `guestbook` VALUES (212, 211)
/
UPDATE `guestbook`
SET `ThreadId` = 212
WHERE `Id` = 211
/
Astute observers will have noticed that we have still ended up with a co-dependency, only between records. So we haven't really advanced; we now have two records we cannot delete, instead of one. (Incidentally this applies to whatever DML we might execute while the foreign key is dropped or disabled). So, perhaps we need to reconsider of the data model. Are we modelling a graph with circular dependencies or a hierarchy?
A hierarchical data structure needs at least one root node, a record on which other records can depend but which itself depends on no record. The usual way of implementing this is to make the foreign key column optional. At the toppermost level of the hierarchy the record must have a NULL in that column. Whether there should be only one such root node or whether several would be allowed is a matter for your business rules.
ALTER TABLE `guestbook` MODIFY `ThreadId` int(10) unsigned
/
In modelling terms this is not different from a record which is its own master, but it is a more intuitive solution.
The inability to delete a self-referencing row is a longstanding known bug/outstanding feature request in MySQL.
In many situations where you rub up against this problem you can NULL the foreign key before executing the delete, so your workaround affects only the rows you intend (uses the same WHERE clause).
Ya temporarily disable the foreign key
set foreign_key_checks=0;
If you set an ON DELETE SET NULL on my Foreign Key, it let's me delete a self-referencing. If I don't specify an ON DELETE, MySQL defaults to RESTRICT.
Of course, make sure the column is NULLABLE. You may also try SET DEFAULT depending on what the default is. But remember NO ACTION is just an alias to RESTRICT in MySQL!
Only tested on MySQL 5.6 (which was not released when this question was originally posted).
I'm currently in the process of converting one of our main ID columns from an INT to a STRING in a MySQL database. The process is pretty simple,
Remove all foreign keys that reference the column (you can't modify it with foreign keys in place)
Modify the ID column and all columns that reference it in other tables
Add the foreign keys back in
Everything is working except for 1 foreign key in step 3 where I get the following error,
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`cp`.`#sql-1_13`, CONSTRAINT `widgets_candidate_id_foreign` FOREIGN KEY (`candidate_id`) REFERENCES `candidates` (`id`))
I'm no stranger to this error. It usually means I got a column name wrong or something, but in this case I'm pretty sure I haven't unless I'm going mad. See snipped table exports below,
CREATE TABLE `candidates` (
`id` varchar(32) COLLATE utf8_unicode_ci NOT NULL,
---- SNIP ----
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `widgets` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`candidate_id` varchar(32) COLLATE utf8_unicode_ci NOT NULL,
---- SNIP ----
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2203 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC
And the MODIFY query is,
ALTER TABLE `widgets`
ADD CONSTRAINT widgets_candidate_id_foreign FOREIGN KEY (`candidate_id`) REFERENCES `candidates` (`id`);
The only thing I think it could be is the ROW_FORMAT=DYNAMIC on the widgets table. Could candidate_id be stored off-page, hence causing the issue?
Any ideas?
Thanks.
You can add a foreign key to a table that already has data in it, but only if the child row exists for each row in the parent table. Based on the error that you are receiving, I would consider that you have a value in your child table that has somehow become deprecated in your parent table.
You can look into this further Here.
You can either use a left join or an IN to see which value exist in the child table that does not exist in the parent. There are other ways to go about solving this issue but how you attack the problem is really what makes sense to you in your particular environment.
I have a table with a natural key and another with a foreign key constaint to it:
create table A
(
id varchar(255) not null primary key
...
)
create table B
(
a_id varchar(255) not null
...
foreign key (a_id) references A (id)
)
I would like to execute a transformation on A.id, (in this specific case lowercasing it) and simulataneously on B.a_id.
Obviously if I do:
update A set id=lower(id);
update B set a_id=lower(a_id);
Than I will get a foreign key constraint violation on the first update.
Is there anyway to execute the two updates "simultaneously", or can you recommend another way to deal with this?
Simplest Approach might be to Drop the constraint,
Perform Update Queries
Again, Introduce the Foreign Key Constraint.
drop the constraint and re-create the constraint with ON UPDATE CASCADE
then execute the update stament on the parent table no child table would get modified.
ALTER TTABLE b ADD CONSTARINT fk_const
FOREIGN KEY(a_id) REFERENCE a (id) ON UPDATE CASCADE
now execute this update
update A set id=lower(id);
In phpMyAdmin when i try to add foreign key some error occurs and does not tell what is wrong. Just says "FK fails".
Can any one tell what is the problem?
Error
SQL query:
ALTER TABLE `hotel` ADD FOREIGN KEY ( `type_id` ) REFERENCES `hotel`.`hotel_type` (
`id`
) ON DELETE CASCADE ON UPDATE CASCADE ;
MySQL said: Documentation
#1452 - Cannot add or update a child row: a foreign key constraint fails (`hotel`.`#sql-cfc_e`, CONSTRAINT `#sql-cfc_e_ibfk_2` FOREIGN KEY (`type_id`) REFERENCES `hotel_type` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
Be sure the columns of both tables are of the same data-type:
hotel.hotel type_id int(11) unsigned # type_id column of hotel table
hotel.hotel_type id int(11) unsigned # id column of hotel_type table
If they are not of the same type then you won't be able to add your FK constraint.
-- Edit --
Based on your response, the columns are the same data-types, so that means you have an invalid value in the hotels.type_id column (value doesn't exist in the hotel_types table). Check the values in your hotels.type_id column and make sure they exist in your hotel_types.id column.
Well there can be a lot of reasons for which you can't create a foreign key. I have found a very interesting article, which I suggest you to read it closely. Maybe something will help you. You can also find very important infos in the MySQL manual, regarding the "FOREIGN KEY Constraints".
Hope this helped.
There are some data in your table that no longer exist in other table, and actually this is against foreign key rules.
If you don't need their data, truncate both tables, and add the foreign key otherwise you should add all the foreign keys one by one.
Here is a query that will find those rows:
select sourcecode_id from
sourcecodes_tags tags left join sourcecodes sc on tags.sourcecode_id=sc.id
where sc.id is null;
Remove the ON DELETE CASCADE ON UPDATE CASCADE
Although this is old, I thought I would share that the way I resolved this was by checking that the encoding and the collation were the same on both sides which for some reason were different.
This fixed the issue.