SQL: Auto-reference table on update cascade - mysql

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.

Related

Multiple foreign key constraints to same table and column fails on update

I've created two tables to do mappings between users. First for users and second for user-mappings. Deletion of users work well, but if I try to update the user id the foreign key constraints from the mapping table fail (without a helpful error output).
CREATE TABLE user (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(55),
PRIMARY KEY (`id`)
);
CREATE TABLE user_map (
map_id INT NOT NULL AUTO_INCREMENT,
user_a INT,
user_b INT,
PRIMARY KEY (`map_id`),
UNIQUE KEY `one_way` (`user_a`,`user_b`),
UNIQUE KEY `other_way` (`user_b`,`user_a`),
CONSTRAINT `acc_connections_ibfk_1` FOREIGN KEY (`user_a`) REFERENCES `user` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT `acc_connections_ibfk_2` FOREIGN KEY (`user_b`) REFERENCES `user` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
Example Data:
INSERT INTO user (name) VALUES ("User A");
INSERT INTO user_map (user_a,user_b) VALUES (1,1);
If I try to update the user id afterwards I get the following error:
Cannot add or update a child row: a foreign key constraint fails
(`test_db`.`user_map`, CONSTRAINT `user_map_ibfk_2`
FOREIGN KEY (`user_b`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
DB Fiddle (Demo)
Interestingly deleting the parent row (user table) succeeds without an error.
What am I doing wrong? I see no reason why this should fail.
I don't know if this is a bug or intended behavior.
As a workaround, if your version of MySql is 8.0.13+, which supports Functional Key Parts, you can use 1 UNIQUE KEY (to check the uniqueness of the combination of the 2 columns) instead of the 2 keys and the UPDATE statement will work:
CREATE TABLE IF NOT EXISTS user_map (
map_id INT NOT NULL AUTO_INCREMENT,
user_a INT,
user_b INT,
PRIMARY KEY (`map_id`),
UNIQUE KEY unk_users((LEAST(`user_a`,`user_b`)), (GREATEST(`user_a`,`user_b`))),
CONSTRAINT `acc_connections_ibfk_1` FOREIGN KEY (`user_a`) REFERENCES `user` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT `acc_connections_ibfk_2` FOREIGN KEY (`user_b`) REFERENCES `user` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
);
See the demo.

Mysql on update cascade not working with tree table [duplicate]

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

How to update column with foreign key constraint within same table

In MySQL I want to update an ID-column of a table that is referenced in a foreign key constraint within that same table.
Example code:
CREATE TABLE A (
A_id int,
parent_A_id int,
PRIMARY KEY (A_id),
CONSTRAINT parent_A FOREIGN KEY (parent_A_id) REFERENCES A (A_id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
INSERT INTO A VALUES (0, NULL), (1, 0);
Now I try to update the column A_id with
UPDATE A SET A_id = A_id + 1;
Unfortunately this throws an error:
Cannot delete or update a parent row: a foreign key constraint fails
I don't really understand why this fails and I can't find anything in the MySQL docs mentioning this not being allowed.
So, why does this not work?
And in the case that I don't just do a stupid mistake:
Is there any better way of doing such an update other than setting foreign_key_checks = 0 and doing everything by hand?
My problem with this would be that I'd like to use the ON UPDATE CASCADE to let the DB handle all foreign key updates for me.

Is there is any way to use ON DELETE CASCADE feature in adhoc basis using query when ON DELETE RESTRICT is defined?

I've created foreign key as ON DELETE RESTRICT but sometimes I need to delete child records along with deletion of the parent record. I can't use "ON DELETE CASCADE" because I need that restriction more often. So is there any way to change the behavior of the foreign key in runtime using any keyword or something in the query like below?
delete * from table1 where ID='3' CASCADE CHILD;
or
delete * from table1 where ID='3' SET foreign_key_behavior= 'ON DELETE CASCADE';
No, there's no syntax for forcing an ad hoc cascading delete if you didn't define the foreign key constraint with the ON DELETE CASCADE option.
Doing the DELETE against both tables in a join doesn't work in MySQL, despite the suggestion from #RaymondNijland in the comments.
Demo using MySQL 5.6:
mysql> create table foo ( id serial primary key );
mysql> create table bar (foo_id bigint unsigned not null,
foreign key (foo_id) references foo(id));
mysql> insert into foo values (1);
mysql> insert into bar values (1);
mysql> delete foo.*, bar.* from foo join bar on foo.id=bar.foo_id where foo.id=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint
fails (`test`.`bar`, CONSTRAINT `bar_ibfk_1` FOREIGN KEY (`foo_id`) REFERENCES
`foo` (`id`))
You'll have to execute a separate delete for each child table, then a delete for the parent table.

MySql "cannot update parent row" when I have "ON UPDATE CASCADE"

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