Get the value when a MySQL constraint fails - php

Assuming I am inserting rows in a MySQL table with a constraint
CREATE TABLE `parent` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
;
CREATE TABLE `child` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`id_parent` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_parent_child` (`id_parent`),
CONSTRAINT `FK_parent_child` FOREIGN KEY (`id_parent`) REFERENCES `parent` (`id`),
)
ENGINE=InnoDB
;
Then when I do an insert in the child table without the entry in the parent table:
INSERT INTO child (id, id_parent) VALUES (1, 1);
I get the following error:
Cannot add or update a child row: a foreign key constraint fails (`...`.`child`, CONSTRAINT `FK_parent_child` FOREIGN KEY (`id_parent`) REFERENCES `parent` (`id`))`
But is there a way to retrieve the value of the insert-failed row, aka 1 here? Because when I insert thousands of rows at the same time, it would be very useful to get the failed one.
I would like a fully-MySQL way, but a PHP way would work too in my case.

Related

Error while inserting the recordsCannot add or update a child row: a foreign key constraint fails

I have created tables in MYSQL as follows
Author Table
CREATE TABLE `author` (
`AuthorId` varchar(25) NOT NULL,
`AuthorName` varchar(50) NOT NULL,
PRIMARY KEY (`AuthorId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Books Table
CREATE TABLE `books` (
`DocId` int(11) NOT NULL,
`ISBN` varchar(13) NOT NULL,
PRIMARY KEY (`DocId`),
KEY `DocId` (`DocId`),
CONSTRAINT `books_ibfk_1` FOREIGN KEY (`DocId`) REFERENCES `document`
(`DocId`)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Document Table
CREATE TABLE `document` (
`DocId` int(11) NOT NULL,
`Title` varchar(50) NOT NULL,
`PublishDate` date DEFAULT NULL,
`AuthorId` varchar(10) DEFAULT NULL,
`DocType` varchar(10) DEFAULT NULL,
PRIMARY KEY (`DocId`),
KEY `AuthorId` (`AuthorId`),
CONSTRAINT `document_ibfk_3` FOREIGN KEY (`AuthorId`) REFERENCES `author`
(`AuthorId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
I made a server for my PHP website on XAMPP and am using mysql but when I try inserting the values in Document table I get
error while inserting the recordsCannot add or update a child row: a foreign
key constraint fails (`librarydb`.`document`, CONSTRAINT `document_ibfk_3`
FOREIGN KEY (`AuthorId`) REFERENCES `author` (`AuthorId`))
How do I resolve this issue?
Your linked fields author.AuthorId and document.AuthorId are not defined the same way.
From the docs:
Corresponding columns in the foreign key and the referenced key must
have similar data types. The size and sign of integer types must be
the same. The length of string types need not be the same.
So make them both varchar(10) NOT NULL - or whatever you need.

One to many relationship in SQL - foreign key error

I am trying to create a campus structure. So buildings have floors, floors have rooms. I am trying to create a relational database such that multiple rooms relate to one floor and multiple floors relate to their building.
Here is my structure for the building and floor tables:
CREATE TABLE `building` (
`id` int(11) NOT NULL,
`name` varchar(128) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
CREATE TABLE `floor` (
`id` int(11) NOT NULL,
`building_id` int(11) DEFAULT NULL,
`level` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `floor_building_id__fk` (`building_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
I want to insert more than one floor in the floor table relating to the same building_id using:
INSERT INTO `floor` SET id=3, `number` = 420, building_id=(SELECT id FROM building WHERE id=2);
However I keep getting the following error:
Error Code: 1452. Cannot add or update a child row: a foreign key constraint fails (`seatspace`.`floor`, CONSTRAINT `building_id` FOREIGN KEY (`id`) REFERENCES `building` (`id`))
I want to insert, update and delete floors relating to their specified building_id. Any help would be appreciated.
I have fixed the problem by changing the constraint name for the foreign key. I also rewrote parts of the schema so all of the desired columns were present. Here is the final schema and CRUD.
CREATE TABLE `floor` (
`floor_id` int(11) NOT NULL AUTO_INCREMENT,
`number` int(11) NOT NULL,
`building_id` int(11) NOT NULL,
PRIMARY KEY (`floor_id`),
UNIQUE KEY `floor_id_UNIQUE` (`floor_id`),
KEY `building_id_idx` (`building_id`),
CONSTRAINT `building_id` FOREIGN KEY (`building_id`) REFERENCES `building`
(`building_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
INSERT INTO `floor` (floor_id, `number`, building_id) VALUES (default, 3,
(SELECT building_id FROM building WHERE building_id=2)) ;
UPDATE `floor` SET `number`=3, building_id=1 WHERE floor_id=2;
DELETE FROM `floor` WHERE floor_id=3;
CREATE TABLE `building` (
`building_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`building_id`),
UNIQUE KEY `building_id_UNIQUE` (`building_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
INSERT INTO building (building_id, name) VALUES (DEFAULT, '1 West');
UPDATE `building` SET `name`='3 West' WHERE building_id=2;
DELETE FROM `building` WHERE building_id=2;

How to perform MySQL UPSERT

This is how my table looks like.
CREATE TABLE `answers` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`basicinfo_id` INT(11) NOT NULL,
`question_id` INT(11) NOT NULL,
`answer` INT(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `question_id` (`question_id`),
INDEX `basicinfo_id` (`basicinfo_id`),
CONSTRAINT `basicinfo_id` FOREIGN KEY (`basicinfo_id`) REFERENCES `basic_info` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT `question_id` FOREIGN KEY (`question_id`) REFERENCES `questions` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION) COLLATE='latin1_swedish_ci' ENGINE=InnoDB AUTO_INCREMENT=3383;
This is how the data can look like
I want to update the answers if they already exist for "basicinfo_id".
OR
If I change the answer for question_id 1, 2 and 3. How can i upsert the data.?
I have tried this query but it doesn't update the result.
INSERT INTO answers (basicinfo_id, question_id, answer) VALUES('98', 1, '1'),('98', 2, '1'),('98', 3, '1'),('98', 4, '1'),('98', 5, '1') ON DUPLICATE KEY UPDATE basicinfo_id = 98;
I have defined a composite unique key now and this is how it looks like but it still didn't work.
CREATE TABLE `answers` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`basicinfo_id` INT(11) NOT NULL,
`question_id` INT(11) NOT NULL,
`answer` INT(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `basicinfo_id_question_id` (`basicinfo_id`, `question_id`),
INDEX `question_id` (`question_id`),
INDEX `basicinfo_id` (`basicinfo_id`),
CONSTRAINT `basicinfo_id` FOREIGN KEY (`basicinfo_id`) REFERENCES `basic_info` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT `question_id` FOREIGN KEY (`question_id`) REFERENCES `questions` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION ) COLLATE='latin1_swedish_ci' ENGINE=InnoDB AUTO_INCREMENT=3718;
Your ON DUPLICATE KEY UPDATE basicinfo_id = 98; is malformed
Try this :
ON DUPLICATE KEY UPDATE 'answer' = VALUES('answer');
If a unique key already exists it will update the answer field

MYSQL #1136 - Column count doesn't match value count at row 1 though they are equal

I keep getting the following error though no. of columns and no. of values match, so I wonder can someone help ?
INSERT INTO `user_dates` (`id`, `date`, `user_id`) VALUES(26545, '2016-04-28', 35);
My Table structure is:
CREATE TABLE `user_dates` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`date` date NOT NULL,
`user_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `user_dates_user_id_foreign` (`user_id`),
CONSTRAINT `user_dates_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=10459 DEFAULT CHARSET=utf8;

ID auto increase but not unique

I have a table that I want to have an id that will auto increase itself but not be primary or unique.
Is this possible?
You should really create another table, in that case.
E.g.
CREATE TABLE `Calls` (
`Id` INT(10) AUTO_INCREMENT,
`From` VARCHAR(100) NOT NULL,
`To` VARCHAR(100) NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=INNODB;
CREATE TABLE `CallHistory` (
`Id` INT(15) AUTO_INCREMENT,
`CallId` INT(10) NOT NULL,
`Text` VARCHAR(255) NOT NULL,
PRIMARY KEY (`Id`),
KEY `CallHistory_Calls_idx` (`CallId`),
CONSTRAINT `CallHistory_Calls`
FOREIGN KEY (`CallId`)
REFERENCES `calls` (`Id`)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=INNODB;
Here's a demo on SQLFiddle.
A benefit of this is that if you delete a row from Calls, the rows in CallHistory will also be deleted.
Running this query:
SELECT `Calls`.`Id`,
`Calls`.`From`,
`Calls`.`To`,
`CallHistory`.`Text`
FROM `Calls`, `CallHistory`
WHERE `Calls`.`Id` = `CallHistory`.`CallId`;
Gives results something like this:
This should work:
id int NOT NULL AUTO_INCREMENT
Anyway I don't see how it wouldn't stay unique unless you update existing values later
Yes, you need to set auto_increment constraint:
CREATE TABLE `test` (
`testID` int(11) NOT NULL, //primary key here
`testInc` int(11) NOT NULL AUTO_INCREMENT, //here is your non-primary auto increment column
PRIMARY KEY (`testID`),
KEY `testInc` (`testInc`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
and if you want this to be unique also then you may add unique constraint:
ALTER TABLE `test` ADD CONSTRAINT ux_unique_constraint UNIQUE `testInc`

Categories