mysql foreign key error #1452 - mysql

ALTER TABLE `groups` ADD FOREIGN KEY ( `company_id` ) REFERENCES `summaries`.`companies` (
`id`
) ON DELETE CASCADE ;
MySQL said:
#1452 - Cannot add or update a child row: a foreign key constraint fails (`summaries/#sql-164a_33c`, CONSTRAINT `#sql-164a_33c_ibfk_1` FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE)
companies.id is primary auto increment int(11)
company_id is index int(11)
I don't understand the error message. Can anyone shed some light on this?

That means you have at least one row in the child table that references a non-existent row in the parent table.
If you are absolutely sure that you are okay with having a data integrity issue like that, you can add the foreign key by disabling foreign key checks before you run the ALTER TABLE command:
SET FOREIGN_KEY_CHECKS = 0;

I just had this problem, although in a somewhat more specific scenario.
In my case, I had added, to an existing table, a column that I needed to be both nullable and act as a foreign key (i.e., for non-null entries to be bound by a foreign key constraint).
The referenced column looked like this:
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
+-------------+-------------+------+-----+---------+----------------+
and the referencing one like this:
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| bed_id | int(10) | YES | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
Turned out that I had forgotten to specify DEFAULT NULL when adding the referencing column to the existing table and so it was automatically filled with zeros, which failed the foreign key constraint.
I changed them to NULL:
update devices set bed_id = NULL where bed_id = 0;
and then successfully added the foreign key constraint. Hope this helps someone

It looks like it tried to copy the groups table to a temp table in the summaries database.
MySQL tried to put the requested constraints on the temp table first. There may possibly be one or more rows in the groups table (hence the temp table also) whose company_id is no longer present in the summaries.companies table.
To verfiy : Try running a LEFT JOIN between groups and summaries.companies WHERE companies.id is NULL. If you get back any rows from that LEFT JOIN, you found the bad rows in the groups table.
Give it a Try !!!

Checks that "companies" table is not empty,if is empty and you have no data at moment.
set SET FOREIGN_KEY_CHECKS = 0;
like Ike said you before.

Related

MySQL add primary key after foreign key insert

I have two tables (A, B) with a foreign key from B to A.
So A is my parent table and B my child.
I now insert a row in B before the parent row exists in A. So I set the foreign key to an id I know parent A will have, but which is not existing right know. To achieve that I use the option 'SET foreign_key_checks = 0', which allows to set a foreign key in the child B without the existens of the key in the parent A.
My question is, what will happen, if I add the row in A with the missing primary key. Will the foreign key <-> primary key connection work and will it be as fast as normal? Or do I have to drop the fk key and rebuild it?
I use InnoDB and MySQL 5.5.
... and I know that is probably very bad practice...
Or short:
I have a parent and a child table, linked by a foreign key. I add the child first, what happens if I add the parent later?
My question is, what will happen, if I add the row in A with the
missing primary key. Will the foreign key <-> primary key connection
work and will it be as fast as normal? Or do I have to drop the fk key
and rebuild it?
If you will add missing record into parent table, the FK constraint will work as it should be. You will actually solve the data inconsistency.
There is no need to recreate FK.
I tried it myself by creating an example.
CREATE TABLE `parent` (
`idparent` int(11) NOT NULL,
PRIMARY KEY (`idparent`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `parent` (
`idparent` int(11) NOT NULL,
PRIMARY KEY (`idparent`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
SET foreign_key_checks = 0;
INSERT INTO child (idchild, parentid) VALUES (1,1),(2,2),(3,3),(4,4),(5,5);
SET foreign_key_checks = 1;
INSERT INTO parent (idparent) VALUES (1),(2),(3),(4),(5);
Next, I used explain to get an idea, if the index is used:
EXPLAIN SELECT * from parent p
join child c on c.parentid = p.idparent;
+----+-------------+-------+-------+-----------------+-----------------+---------+----------------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-----------------+-----------------+---------+----------------------+------+--------------------------+
| 1 | SIMPLE | p | index | PRIMARY | PRIMARY | 4 | NULL | 5 | Using index |
| 1 | SIMPLE | c | ref | fk_parentid_idx | fk_parentid_idx | 5 | remove_me.p.idparent | 1 | Using where; Using index |
+----+-------------+-------+-------+-----------------+-----------------+---------+----------------------+------+--------------------------+
So it looks like it uses the index, altough at first the foreign key was not set. Therefore, it should be at least speedwise no problem.
INSERT INTO `area` (
`area_id` PRIMARY KEY,
`area_name`,
`chemist_id`FOREIGN KEY
)
VALUES (
[value-1],
[value-2],
[value-3]
)

Mysql create table with two foreign keys referencing primary key

I have two mysql tables. The first one is created using the following code:
create table project(
project_id int not null auto_increment,
project_name varchar(30)
primary key(project_id));
The second table:
create table matches(
match_id int not null auto_increment,
match_name varchar(30),
project_id int(4) foreign key (project_id) references projects(project_id));
Both these commands works fine. I want to add the project_name column from the first table to the second table. I tried using
alter table projects drop primary key, add primary key(project_id, project_name);
and then
alter table matches add column project_name varchar(30), add foreign key (project_name) references projects(project_name);
But got the following error:
ERROR 1005 (HY000): Can't create table 'matches.#sql-55e_311' (errno: 150)
How do i include both the columns from the first table into the second table.
The current structure of my second table is as follows:
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| match_id | int(11) | NO | PRI | NULL | auto_increment |
| match_name | varchar(30) | YES | | NULL | |
| project_id | int(4) | NO | MUL | NULL | |
+------------+-------------+------+-----+---------+----------------+
I want to add the project_name as the fourth column in my second table.
To use a compound Primary Key as Foreign Key, you'll have to add the
same number of columns (that compose the PK) with same datatypes to
the child table and then use the combination of these columns in the
FOREIGN KEY definition.
see related post here https://stackoverflow.com/a/10566463/4904726
so try this way
alter table matches add foreign key (project_id, project_name) references projects(project_id, project_name);
Do you understand what a FK constraint says? It says a list of values for some columns in a table must appear as a list of values for some columns forming a (declared) PK or UNIQUE NOT NULL in the referenced table. So what you are writing doesn't make sense. If you wanted a PK (project_id, project_name) then that should also be the form of your FK.
But (project_id, project_name) is not two 1-column PKs, it is one 2-column PK, and it is probably not what you want since presumably in projects it isn't just pairs that are unique it is each column. Presumably you want two 1-column PKs and two one-column FKs, one referencing each PK.
If projects project_id was NOT NULL you could write:
alter table projects add primary key(project_name);
alter table matches add column project_name varchar(30),
add foreign key (project_name) references projects(project_name);
But if project_name can be NULL in projects then you cannot make it a PK and you cannot sensibly have a FK to it. You can make it UNIQUE. Unfortunately MySQL lets you write such a FK declaration to a non-NULL UNIQUE column while it also tells you not to do it:
The handling of foreign key references to non-unique keys or keys that contain NULL values is not well defined for operations such as UPDATE or DELETE CASCADE. You are advised to use foreign keys that reference only keys that are both UNIQUE (or PRIMARY) and NOT NULL.
So if you want projects project_name to be nullable then should declare it UNIQUE but you should enforce the logical matches project_name match with a trigger.

Can the primary key referenced by a foreign key be a varchar(255) in mysql?

I've run this query on mysql:
ALTER TABLE `connections`
ADD CONSTRAINT `connections_serial_fk`
FOREIGN KEY (`serial`)
REFERENCES `devices`(serial)
ON DELETE CASCADE;
And I'm getting error number 150. I already looked for the documentation and the thing I think that may be causing this error is that the column 'serial' is a varchar(255).
This reference says "innodb permits a foreign key to reference any index column or group of columns".
Does MySql have this restriction?
From my schema:
devices:
| Field | Type | Null | Key | Default | Extra |
| serial | varchar(255) | YES | | NULL | |
connections:
| Field | Type | Null | Key | Default | Extra |
| serial | varchar(255) | YES | | NULL | |
A dbms that conforms to standard SQL will prevent you from setting a foreign key reference to a column (or columns) that doesn't have some kind of unique constraint on it--either PRIMARY KEY or UNIQUE. But MySQL does permit this kind of nonsense under certain circumstances.
Additionally, MySQL requires that the referenced columns be indexed
for performance reasons. However, the system does not enforce a
requirement that the referenced columns be UNIQUE or be declared NOT
NULL. The handling of foreign key references to nonunique keys or keys
that contain NULL values is not well defined for operations such as
UPDATE or DELETE CASCADE. You are advised to use foreign keys that
reference only UNIQUE (including PRIMARY) and NOT NULL keys.
Foreign keys should reference only a column (or columns) that have been declared either PRIMARY KEY or NOT NULL UNIQUE. If you think you need a foreign key reference to a nonunique column or columns, that's a big red flag, waving in your face, held by a guy yelling, "You have a design problem!"

Mysql errno 150 trying to create table with foreign key references

I'm trying to create a table in mysql with a foreign key reference, like this:
In database A:
CREATE TABLE replication (
id varchar(255) NOT NULL PRIMARY KEY,
uid varchar(255) NOT NULL,
value int(11) NOT NULL,
FOREIGN KEY (uid) REFERENCES databaseB.users(username)
);
In database B i have a table named users like this:
+-----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+-------+
| id | varchar(255) | NO | | NULL | |
| username | varchar(255) | NO | PRI | NULL | |
+-----------------+--------------+------+-----+---------+-------+
When i try to create table replication, gives me the following error:
ERROR 1005 (HY000): Can't create table 'databaseA.replication' (errno: 150)
Any idea? Thanks in advance!
You need to add an index to uid or you will not be able to set it up to reference anything.
Also, typically in your DatabaseB you would have your users table have a Primary Key on ID and a unique index on username. Then you would set up a foreign key from DatabaseA.replication REFERENCES databaseB.users(id)
you cant make reference key with two different types
in databaseA is integer uid and databaseB is varchar
try this
FOREIGN KEY (uid) REFERENCES databaseB.users(id)
Are both databases of the same type (MyISAM, INNODB)? You cannot point a foreign key to a MyISAM DB.
This error can also occur when you are mixing types for the field type (which is the same in this case, varchar(255)), or when the encodings of the fields are different.
Another reason could be that you don't have access to the other database.
Thetype of the field in a foreign key must be the same as the type of the column they're referencing.I think this problem error because type of the field in a foreign key is different from the column they're referencing.
Your foreign key field is uid and referencing table your field is username.Here is the problem.Try to use same type of field in both table like
FOREIGN KEY (uid) REFERENCES databaseB.users(id)
Hope you understand and works for you.

PHP MySQL Delete parent and child rows

I have 1 MySQL Table. It looks like this:
+---------+-------------+--------+
| item_id | parent_id | Name |
+---------+-------------+--------+
| 1 | 0 | Home |
+---------+-------------+--------+
| 2 | 1 | Sub |
+---------+-------------+--------+
| 3 | 2 | SubSub |
+---------+-------------+--------+
If I DELETE item_id 1, I want to delete the rest of the sub also but how can I do it?
I have tried the Foreign Key but it works only if you have 2 tables??
I hope someone can help me in MySQL maybe PHP?
You can, most definitely, use self-referencing foreign keys with MySQL (you don't need multiple tables). However, for any kind of foreign key support, you need to use the InnoDB engine. And my guess is, that you are using the MyISAM engine.
With InnoDB you could create a table, similar to what you have already, including the self-referencing foreign key, like this:
CREATE TABLE `yourTable` (
`item_id` int(10) unsigned NOT NULL auto_increment,
`parent_id` int(10) unsigned default NULL,
`Name` varchar(50) NOT NULL,
PRIMARY KEY (`item_id`),
KEY `FK_parent_id` (`parent_id`),
CONSTRAINT `FK_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `yourTable` (`item_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Then, when you issue a DELETE statement, like:
DELETE FROM `yourTable` WHERE `item_id` = 1;
... it would delete each 'child' row, that has a parent_id of 1 as well. If any of those 'child' rows have children of their own, they'd be deleted too, etc. (that's what the ON DELETE CASCADE means).
Easier actually than thought:
DELETE FROM table WHERE id = # OR parent_id = #; //where # is the same in both places.
Example:
DELETE FROM table WHERE id = 1 OR parent_id = 1;