Fail on foreign constraint key - mysql

I'm trying to create a foreign key between the field review_id in table Reviews and id in table Sentences. The structure of the tables is the following:
CREATE TABLE `Reviews` (
`review_id` varchar(255) CHARACTER SET utf8 NOT NULL,
`package_name` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
`review_content` text CHARACTER SET utf8,
`review_date` date DEFAULT NULL,
`star_rating` int(11) DEFAULT NULL,
`app_version_id` int(11) NOT NULL,
PRIMARY KEY (`review_id`),
KEY `app_version_id` (`app_version_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `Sentences` (
`id` varchar(255) NOT NULL DEFAULT '',
`review` text,
`category` varchar(255) DEFAULT NULL,
`topic` varchar(255) DEFAULT NULL,
KEY `rev-id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I'm facing with the following error and I don't understand what the problem could be.
ALTER TABLE `Reviews` ADD CONSTRAINT `rev-to-sents` FOREIGN KEY (`review_id`) REFERENCES `Sentences` (`id`)
Foreign key constraint fails for table `msr test db`.`#sql-75_d`:
,
CONSTRAINT `rev-to-sents` FOREIGN KEY (`review_id`) REFERENCES `Sentences` (`id`)
Trying to add in child table, in index PRIMARY tuple:
DATA TUPLE: 8 fields;
0: len 36; hex 37626532323335652d616663392d313165362d383935342d633462333031636466363237; asc 7be2235e-afc9-11e6-8954-c4b301cdf627;;
...

The problem sounds like you are trying to add a foreign key with rows that don't match. If so your first task is to find the non-matching rows and determine the scope of the problem In other words you have cases where Reviewes.review_id does not match any value in Sentences.id
You need to find and fix your data first. This means:
SELECT review_id FROM Reviews
LEFT JOIN Sentences ON review_id = Sentences.id
WHERE Sentences.id IS NULL;
Since you have a NOT NULL constraint on Sentences.id, only when the join condition fails, will the id be null.

Try this:
ALTER TABLE Reviews
ADD CONSTRAINT rev-to-sents
ADD FOREIGN KEY (review_id)
REFERENCES Sentences (id)

Related

Error 1215 on adding foreign key. Help me with what I haven't tried

I'm trying to set a foreign key relationship between two existing table but for some reason which I'm missing I keep getting this error 1215.
The relevant fields of the two tables are:
CREATE TABLE `approvals` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_contract` int(11) NOT NULL,
`id_user` int(11) NOT NULL,
`lang` varchar(8) NOT NULL,
`request_ts` datetime NOT NULL,
`version` int(11) NOT NULL,
-- more nullable columns here with no indexing/relationships
PRIMARY KEY (`id`),
KEY `approval_id_user` (`id_user`),
KEY `version` (`version`,`lang`,`id_contract`),
CONSTRAINT `approval_id_user` FOREIGN KEY (`id_user`)
REFERENCES `users` (`iduser`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1079 DEFAULT CHARSET=utf8
CREATE TABLE `version` (
`idversion` int(11) NOT NULL,
`idcontract` int(11) NOT NULL,
`language` varchar(8) NOT NULL,
PRIMARY KEY (`idversion`,`idcontract`,`language`),
KEY `fk_version_contracts_idx` (`idcontract`),
CONSTRAINT `fk_kidversion_contracts` FOREIGN KEY (`idcontract`)
REFERENCES `contracts` (`id_contract`)
ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8
What have I tried
First thing I checked is the persistency:
SELECT * FROM approvals a
WHERE NOT EXISTS (
SELECT 1 FROM version v
WHERE v.idcontract = a.id_contract AND v.language = a.lang
AND v.idversion = a.version);
which resulted in 0 rows returned out of 701, ok my db should be good from the data pov.
So I checked the collation and for some reason the version table was latin1 vs utf8_generic_ci, ok so I restored the version table to utf8 with this.
ALTER TABLE `kidversion`
COLLATE = utf8_general_ci;
-- and for good measure
ALTER TABLE `kidversion`
CHANGE COLUMN `language` `language` VARCHAR(8)
CHARACTER SET 'utf8' COLLATE 'utf8_general_ci' NOT NULL;
But at this point I'm still getting an error while trying to create the foreign key:
ALTER TABLE `approvals`
ADD CONSTRAINT `approval_ibfk_1`
FOREIGN KEY (`version` , `lang` , `id_contract`)
REFERENCES `version` (`idversion` , `language` , `idcontract`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
And that results in a 1215 in every step I made. Surely I'm missing something.. can anyone help me out with this?
FOREIGN KEY (version , lang , id_contract) REFERENCES version (idversion , language , idcontract) AND PRIMARY KEY (idversion,idcontract,language) don't match fields have to be in the same order as well as same type.
'In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order.' - https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html

Simple Relation between 2 tables

I have a problem here.
I cannot add this to my db because one table is dependent of another and vice-versa.
So I get
Cannot add foreign key constraint
on the first create table that I put
How can I add this 2 tables if they both have constraints??
-- User Roles
CREATE TABLE IF NOT EXISTS `user_roles` (
`user_role_id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(45) NOT NULL,
`role` varchar(45) NOT NULL,
PRIMARY KEY (`user_role_id`),
UNIQUE KEY `uni_username_role` (`role`,`username`),
UNIQUE KEY `ix_auth_username` (`username`,`role`),
KEY `fk_username_idx` (`username`),
CONSTRAINT `fk_username` FOREIGN KEY (`username`) REFERENCES `users` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
-- Users
CREATE TABLE IF NOT EXISTS `users` (
`username` varchar(45) NOT NULL,
`name` varchar(45) DEFAULT NULL,
`hashedPassword` varchar(500) NOT NULL,
`enabled` tinyint(1) NOT NULL DEFAULT '1',
`image` mediumblob,
`team` int(11) DEFAULT NULL,
`userRole` int(11) DEFAULT NULL,
PRIMARY KEY (`username`),
KEY `fkteam_idx` (`team`),
KEY `fkrole_idx` (`userRole`),
CONSTRAINT `fkrole` FOREIGN KEY (`userRole`) REFERENCES `user_roles` (`user_role_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fkteam` FOREIGN KEY (`team`) REFERENCES `team` (`idteam`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
To do this, you'll need to use deferrable constraint checks, but unfortunately MySQL does not implement this standard SQL feature.
As far as I know, only Oracle and PostgreSQL support this feature (deferrable constraints). These constraints are checked at the end of the transaction, and not on every single row insertion. That would solve your problem.
Therefore, you have two options:
Switch to Oracle or PostgreSQL (unlikely, I guess) or,
Change your table definition to allow one of the foreign key constraints to accept null values.
In the second case, you would:
Insert in the table that allow null in the FK, getting the generated ID.
Insert in the other table using the ID. Then, get the second generated ID.
Update the null in first table using the second ID.
Commit.
That's it.

MySQL: Cannot add or update a child row: a foreign key constraint fails when referencing UID

I have 2 tables : tbl_usr_info which has a UID which is a primary key and auto-increment and tbl_login_info which has a LoginID (primary) and the UID along with some other information like timestamps etc.
I'm trying to reference UID from tbl_login_info with UID in tbl_usr_info by running this sql statement
CONSTRAINT `uid-info/login` FOREIGN KEY (`UID`) REFERENCES `tbl_usr_info` (`UID`)
but I'm getting this error:
Cannot add or update a child row: a foreign key constraint fails (CONSTRAINT uid-info/login FOREIGN KEY (UID) REFERENCES tbl_usr_info (UID))
tbl_usr_info table
CREATE TABLE `tbl_usr_info` (
`UID` int(50) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL DEFAULT '',
`password` varchar(50) NOT NULL DEFAULT '',
`email` varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (`UID`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
tbl_usr_login table
CREATE TABLE `tbl_usr_login` (
`LoginID` int(11) NOT NULL AUTO_INCREMENT,
`UID` int(50) NOT NULL,
`ip_address` varchar(55) DEFAULT NULL,
`device` varchar(100) DEFAULT NULL,
`time_stamp` datetime DEFAULT NULL,
PRIMARY KEY (`LoginID`)
)ENGINE=InnoDB DEFAULT CHARSET=latin1;
Is it the order in which I'm referencing it that's wrong?
I tested your foreign key constraint and it works without error for me. But my tables were empty.
One of the most common types of failures for a foreign key constraint is that when you create the constraint, the child table contains some values that are not present in the parent table. The foreign key constraint cannot be satisfied in that case, so creation of the constraint fails.
You can check for unmatched UID values:
SELECT COUNT(*)
FROM tbl_usr_login AS l
LEFT OUTER JOIN tbl_usr_info AS i
ON l.UID = i.UID
WHERE i.UID is NULL;
P.S.: This is tangential to your question, but I notice you're using INT(50). The argument to INT doesn't mean what you think it means. INT(50) does NOT mean you can store 50 digits. See my answer to Types in MySQL: BigInt(20) vs Int(20)
To enable foreign key, child and parent column definitions must match along with some other conditions.
In your problem case, following steps should resolve it:
create user table.
create login info table.
add index/key on the UID column in login table.
now, add referential constraint on it.
Refer to:
Mysql: Using foreign key constraints:
https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html

Cannot add or update a child row: a foreign key constraint fails mysql

CREATE TABLE `class` (
`class_id` int(11) NOT NULL AUTO_INCREMENT,
`section_name` varchar(50) NOT NULL,
`class_alias` varchar(200) NOT NULL,
`grading_scheme` int(11) NOT NULL DEFAULT '0',
`year` year(4) NOT NULL,
`grade_calc_method_id` varchar(20) DEFAULT NULL,
PRIMARY KEY (`class_id`)
) ENGINE=InnoDB AUTO_INCREMENT=48819 DEFAULT CHARSET=latin1;
CREATE TABLE `teachers` (
`teacher_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`teacher_subject` varchar(20) NOT NULL DEFAULT 'None',
PRIMARY KEY (`teacher_id`),
KEY `user_id` (`user_id`,`school_id`)
) ENGINE=InnoDB AUTO_INCREMENT=48606 DEFAULT CHARSET=latin1;
CREATE TABLE `teacher_classes` (
`teacher_class_id` int(11) NOT NULL AUTO_INCREMENT,
`teacher_id` int(11) NOT NULL,
`class_id` int(11) NOT NULL,
PRIMARY KEY (`teacher_class_id`),
UNIQUE KEY `teacher_id_class_id` (`teacher_id`,`class_id`),
KEY `teacher_id` (`teacher_id`,`class_id`)
) ENGINE=InnoDB AUTO_INCREMENT=46707 DEFAULT CHARSET=latin1;
Trying to insure data consistency between the tables by using foreign key so that the DBMS can check for errors.I have another junction table teacher_classes
Here is my query to add foreign keys constraint
ALTER TABLE teacher_classes
ADD CONSTRAINT `tc_fk_class_id` FOREIGN KEY (`class_id`)
REFERENCES class (`class_id`) ON UPDATE NO ACTION ON DELETE NO ACTION,
ADD CONSTRAINT `tc_fk_teacher_id` FOREIGN KEY (`teacher_id`)
REFERENCES teachers (`teacher_id`) ON UPDATE NO ACTION ON DELETE NO ACTION;
've seen the other posts on this topic, but no luck, getting following error.
Cannot add or update a child row: a foreign key constraint fails
(DB_NAME.#sql-403_12, CONSTRAINT
tc_fk_teacher_id FOREIGN KEY (teacher_id) REFERENCES teachers
(teacher_id) ON DELETE NO ACTION ON UPDATE NO ACTION)
Too late to Answer. I just had the same problem the solution is easy.
You're getting this error because you're trying to or UPDATE a row to teacher_classes doesn't match the id in table teachers.
A simple solution is disable foreign key checks before performing any operation on the table.
SET FOREIGN_KEY_CHECKS = 0;
After you are done with the table enable it again.
SET FOREIGN_KEY_CHECKS = 1;
Or you can remove not null constraint and insert a NULL value in it.
That's most probably the column definition doesn't match properly. For table teachers the PK column definition is as below.
`teacher_id` int(11) NOT NULL AUTO_INCREMENT
Make sure you have the same definition in your child table teacher_classes

What is the difference between these two SQL queries?

I've created table Address with this SQL query:
CREATE TABLE `address` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`Street` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`Number` smallint(6) DEFAULT NULL,
`other_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`other_id`) REFERENCES `other` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
But there's also this query:
CREATE TABLE `address` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`Street` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`Number` smallint(6) DEFAULT NULL,
`other_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `other_id` (`other_id`),
CONSTRAINT `adress_ibfk_1` FOREIGN KEY (`other_id`) REFERENCES `other` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci$$
and it seems that booth query create identical tables.
So can anyone explain to me what does this line do:
KEY `other_id` (`other_id`),
and what is the difference between these two lines:
FOREIGN KEY (`other_id`) REFERENCES `other` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
and
CONSTRAINT `adress_ibfk_1` FOREIGN KEY (`other_id`) REFERENCES `other` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
If the difference between last two lines is that latter gives name 'adress_ibfk_1' to foreign key ? If that's true - should I do it ? I mean, why should I name foreign keys ? Will I ever need their names ?
Thanks ! :)
MySQL interprets KEY as an index, so the second query creates an index on the column other_id.
The difference between the two FK declaration is that you manually set the name in the second line. In the first line, MySQL automatically sets a name.
They do need names, but you don't necessarily have to be aware of them. Some more advanced RDBMS use them to be more explicit when a query raises an error.
KEY is a synonym for INDEX, so that is creating an index on the other_id column.
The only difference in the foreign key construction is that the latter constraint version allows you to name the constraint, whereas the former will be given a system generated name.
This name can be seen in the INFORMATION_SCHEMA TABLE_CONSTRAINTS table.