I have a relationship with tables (technical and problems) in the table have 3 states (in, waiting, out) in which the technical from the other table is selected.
Relation
the problem is that when I try to change the ID of a technician gives me the following error:
#1452 - Cannot add or update a child row: a foreign key constraint fails (`demo_stack`.`problem`, CONSTRAINT `problem_ibfk_1` FOREIGN KEY (`technical_id_in`) REFERENCES `technical` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
Update:
UPDATE `technical` SET `id` = '14' WHERE `technical`.`id` = 1
Tables:
CREATE TABLE technical (
id INT NOT NULL AUTO_INCREMENT,
name varchar(255),
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE problem (
id INT,
name varchar(255),
technical_id_in INT,
technical_id_waiting INT,
technical_id_out INT,
INDEX (technical_id_in,technical_id_waiting,technical_id_out),
FOREIGN KEY (technical_id_in) REFERENCES technical(id) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (technical_id_waiting) REFERENCES technical(id) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (technical_id_out) REFERENCES technical(id) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=INNODB;
INSERT INTO `technical` (`id`, `name`) VALUES ('1', 'victor'), ('2', 'eduardo'), ('3', 'jose');
INSERT INTO `problem` (`id`, `name`, `technical_id_in`, `technical_id_waiting`, `technical_id_out`) VALUES ('1', 'Problem 1', '1', '2', '1'), ('2', 'Problem 2', '1', '1', '1');
anyone have any idea? Thanks !!!
The suggestion of the MySql reference manual:
START TRANSACTION;
SET foreign_key_checks = 0;
UPDATE technical SET id = 14 WHERE ID = 1;
UPDATE problem SET technical_id_in = 14 WHERE technical_id_in = 1;
UPDATE problem SET technical_id_waiting = 14 WHERE technical_id_waiting = 1;
UPDATE problem SET technical_id_out = 14 WHERE technical_id_out = 1;
SET foreign_key_checks = 1;
COMMIT TRANSACTION;
-- or "ROLLBACK TRANSACTION" if anything fails
You have to update all the foreign keys by yourself.
Also make sure, that you run this script within a transaction, and that you rollback the transaction if it anything fails.
Related
So, I am getting:
Error Code: 1451. Cannot delete or update a parent row: a foreign key
constraint fails (playground.Person, CONSTRAINT sk_Person_Parent
FOREIGN KEY (parent_id) REFERENCES Person (id) ON DELETE CASCADE
ON UPDATE CASCADE)
This is the simple table, referencing itself:
CREATE TABLE IF NOT EXISTS Person (
id int not null primary key,
name varchar(100) not null,
parent_id int null,
CONSTRAINT `sk_Person_Parent`
FOREIGN KEY (parent_id)
REFERENCES Person (id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
as you see, there is "ON UPDATE CASCADE".
I insert 4 simple rows in it:
INSERT INTO Person(id, name, parent_id)
VALUES
(1, 'vasko', NULL),
(2, 'asdas', 1),
(3, 'ivo', 1),
(4, 'anton', 3);
so I have
1 - vasko
2 - asdasd
3 - ivo
4 - anton.
When i delete by id 1, all the records get wiped, because of the ON DELETE CASCADE. However, if I try to execute
UPDATE Person
SET id=10
WHERE id=1;
I get the given error. Any ideas?
(I am expecting vasil's id to become 10, and the parent_id of the next 2 rows to be updated to 10)
It is limitation in Mysql:
If ON UPDATE CASCADE or ON UPDATE SET NULL recurses to update the same table it has previously updated during the cascade, it acts like RESTRICT. This means that you cannot use self-referential ON UPDATE CASCADE or ON UPDATE SET NULL operations.
reference here
I've created a SQLFiddle with the code shown below. The problem is that after the DELETE statement the associated credit_card record is supposed to be deleted as well.
CREATE TABLE person (
id BIGINT AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE credit_card (
id BIGINT AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE person_credit_card (
person_id BIGINT NOT NULL,
credit_card_id BIGINT NOT NULL UNIQUE, -- Please note that this is UNIQUE
PRIMARY KEY(person_id, credit_card_id),
CONSTRAINT fk__person_credit_card__person
FOREIGN KEY (person_id)
REFERENCES person(id),
KEY pkey (credit_card_id),
CONSTRAINT fk__person_credit_card__credit_card
FOREIGN KEY (credit_card_id)
REFERENCES credit_card(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
INSERT INTO person (id) VALUES (1);
INSERT INTO credit_card (id) VALUES (1);
INSERT INTO person_credit_card (person_id, credit_card_id) VALUES (1, 1);
DELETE FROM person_credit_card WHERE credit_card_id = 1;
I'm not sure why this is not working. With the UNIQUE constraint on the credit_card_id this is not possible:
+--------------------------------------+
| person_credit_card |
+--------------------------------------+
| person_id | credit_card_id |
+--------------------------------------+
| 1 | 1 |
+--------------------------------------+
| 2 | 1 |
+--------------------------------------+
So what am I doing wrong here and how can I make it work?
I also tried to e.g. delete a person and remove all his credit_card records (see this other SQLFiddle):
CREATE TABLE person (
id BIGINT AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE credit_card (
id BIGINT AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE person_credit_card (
person_id BIGINT NOT NULL,
credit_card_id BIGINT NOT NULL UNIQUE,
PRIMARY KEY(person_id, credit_card_id),
CONSTRAINT fk__person_credit_card__person
FOREIGN KEY (person_id)
REFERENCES person(id)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT fk__person_credit_card__credit_card
FOREIGN KEY (credit_card_id)
REFERENCES credit_card(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
INSERT INTO person (id) VALUES (1);
INSERT INTO person (id) VALUES (2);
INSERT INTO credit_card (id) VALUES (1);
INSERT INTO credit_card (id) VALUES (2);
INSERT INTO credit_card (id) VALUES (3);
INSERT INTO person_credit_card (person_id, credit_card_id) VALUES (1, 1);
INSERT INTO person_credit_card (person_id, credit_card_id) VALUES (1, 2);
INSERT INTO person_credit_card (person_id, credit_card_id) VALUES (2, 3);
DELETE FROM person WHERE id = 1;
but the outcome is that only the resolution table is losing its entries but the credit_card records are still there.
From the documentation:
CASCADE: Delete or update the row from the parent table, and
automatically delete or update the matching rows in the child table.
Both ON DELETE CASCADE and ON UPDATE CASCADE are supported.
Deleting from person_credit_card won't cascade person nor credit_card.
Cascade works by deleting/updating records from tables that reference the record being deleted.
In other words, since person doesn't have a column with reference to person_credit_card, then it won't be deleted.
So, I am getting:
Error Code: 1451. Cannot delete or update a parent row: a foreign key
constraint fails (playground.Person, CONSTRAINT sk_Person_Parent
FOREIGN KEY (parent_id) REFERENCES Person (id) ON DELETE CASCADE
ON UPDATE CASCADE)
This is the simple table, referencing itself:
CREATE TABLE IF NOT EXISTS Person (
id int not null primary key,
name varchar(100) not null,
parent_id int null,
CONSTRAINT `sk_Person_Parent`
FOREIGN KEY (parent_id)
REFERENCES Person (id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
as you see, there is "ON UPDATE CASCADE".
I insert 4 simple rows in it:
INSERT INTO Person(id, name, parent_id)
VALUES
(1, 'vasko', NULL),
(2, 'asdas', 1),
(3, 'ivo', 1),
(4, 'anton', 3);
so I have
1 - vasko
2 - asdasd
3 - ivo
4 - anton.
When i delete by id 1, all the records get wiped, because of the ON DELETE CASCADE. However, if I try to execute
UPDATE Person
SET id=10
WHERE id=1;
I get the given error. Any ideas?
(I am expecting vasil's id to become 10, and the parent_id of the next 2 rows to be updated to 10)
It is limitation in Mysql:
If ON UPDATE CASCADE or ON UPDATE SET NULL recurses to update the same table it has previously updated during the cascade, it acts like RESTRICT. This means that you cannot use self-referential ON UPDATE CASCADE or ON UPDATE SET NULL operations.
reference here
MySQL Server version: 5.6.17
I have two tables:
vatbands:
`vatbands_id` INT(11) UNSIGNED NOT NULL,
`client_id` INT(11) UNSIGNED NOT NULL COMMENT 'Customer ID',
`code` ENUM('A', 'B', 'C', 'D', 'E', 'F') NOT NULL,
PRIMARY KEY (`vatbands_id`, `code`, `client_id`),
INDEX `vatcode_vatbands` (`code` ASC, `client_id` ASC)
ENGINE = InnoDB;
1 row in vatbands:
INSERT INTO `vatbands` (`client_id`, `code`) VALUES ('1', 'A');
items:
`client_id` INT(11) UNSIGNED NOT NULL,
`vatcode` ENUM('A', 'B', 'C', 'D', 'E', 'F') NOT NULL DEFAULT 'A',
PRIMARY KEY (`item_id`, `client_id`),
INDEX `vatcode_item` (`vatcode` ASC, `client_id` ASC),
CONSTRAINT `vatcode_item`
FOREIGN KEY (`vatcode` , `client_id`)
ENGINE = InnoDB;
Inserting into child (item) table:
INSERT INTO `item` (`client_id`, `code`) VALUES ('1', '');
When I try to insert into my items table without specifying a vatcode i get foreign key constraint failure:
Cannot add or update a child row: a foreign key constraint fails (`mydb`.`item`, CONSTRAINT `vatcode_item` FOREIGN KEY (`vatcode`, `client_id`) REFERENCES `vatbands` (`code`, `client_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
Why is this, I thought specifying a default value for the vatcode would allow this to continue (as long as the row exists)?
I have checked the InnoDB manual:
14.6.6 InnoDB and FOREIGN KEY Constraints
Referential actions for foreign keys of InnoDB tables are subject to
the following conditions:
While SET DEFAULT is allowed by the MySQL Server, it is rejected as
invalid by InnoDB.
Is this the reason it is failing?
UPDATE:
If i input a value directly using PHP:
INSERT INTO `item` (`client_id`, `code`) VALUES ('1', 'A');
The constraint succeeds as expected.
The SET DEFAULT clause for a foreign key has nothing to do with inserting to the child table. It declares what to do with dependent rows in the child table if the referenced row in the parent table is deleted or updated.
Example: If an employee belongs to a department, and the department is deleted, should the employee be fired as well? Or should they be reassigned to some other "default" department?
I tested your example, and I find that it works fine, but you must specify at least a client_id that exists in the parent table.
mysql> insert into items (client_id) values (1);
Query OK, 1 row affected (0.00 sec)
I also notice that your key in vatbands on (code,client_id) is a non-unique key. It should really be a primary key or unique key to be referenced by a foreign key of a child table. In fact, when I test with MySQL 5.7 milestone release, I can't even create the items table because apparently in this regard the new version of MySQL is more strict than older versions. So I had to make your key a primary key. Then the test worked.
The only way I could get this to work is inserting a default using PHP.
INSERT INTO `item` (`client_id`, `code`) VALUES ('1', 'A');
If anyone has any better ways of resolving this please don't hesitate to comment, I would much prefer a pure MySQL method.
If you use:
INSERT INTO `item` (`client_id`, `code`) VALUES ('1', '');
You are not inserting NULL but an empty string.
INSERT INTO `item` (`client_id`, `code`) VALUES ('1', NULL);
will work
I have a table with a foreign key auto-referenced, like this:
CREATE TABLE user
(
id INT,
name VARCHAR(20),
ref INT,
PRIMARY KEY(id)
)ENGINE=InnoDB;
ALTER TABLE user
ADD FOREIGN KEY (ref) REFERENCES user(id)
ON DELETE RESTRICT ON UPDATE CASCADE;
Then, I insert values in the table:
INSERT INTO user
VALUES(1, "User1", NULL), (2, "User2", 1), (3, "User3", 1), (4, "User4", 3);
SELECT * FROM user;
And I update a user to check if, when I update the id of a user, then the FK is updated on cascade:
UPDATE user
SET id = 5
WHERE id = 1;
But I get this error:
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails ('prueba'.'user', CONSTRAINT 'user_ibfk1' FOREIGN KEY ('ref') REFERENCES 'user' ('id') ON UPDATE CASCADE)
Can anyone say me what I'm doing wrong? Thank you.
see the dev document. Your self-referential "ON UPDATE CASCADE" acts like "ON UPDATE RESTRICT".
http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
If ON UPDATE CASCADE or ON UPDATE SET NULL recurses to update the same table it has previously updated during the cascade, it acts like RESTRICT. This means that you cannot use self-referential ON UPDATE CASCADE or ON UPDATE SET NULL operations. This is to prevent infinite loops resulting from cascaded updates. A self-referential ON DELETE SET NULL, on the other hand, is possible, as is a self-referential ON DELETE CASCADE. Cascading operations may not be nested more than 15 levels deep.