I'm trying to (in a single statement) delete a row and all its relationships, even if all those relationships don't exist. Cascade on delete is not on option, and I would prefer to avoid subqueries.
Here is an example of what fails due to foreign key relationships:
CREATE TABLE test(id integer, title varchar(100), primary key(id));
INSERT into test(id, title) values(1, "Hello");
CREATE TABLE ref_a(id integer, test_id integer, primary key(id), key(test_id), constraint foreign key(test_id) references test(id));
INSERT into ref_a(id, test_id) values(1, 1);
CREATE TABLE ref_b(id integer, test_id integer, primary key(id), key(test_id), constraint foreign key(test_id) references test(id));
SET GLOBAL FOREIGN_KEY_CHECKS=1;
DELETE test, ref_a, ref_b FROM test
LEFT JOIN ref_a ON ref_a.test_id = test.id
LEFT JOIN ref_b ON ref_b.test_id = test.id
WHERE test.id = 1;
This fails with the error
Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails (`product`.`ref_a`, CONSTRAINT `ref_a_ibfk_1` FOREIGN KEY (`test_id`) REFERENCES `test` (`id`))
Is this possible to do?
DB is InnoDb. MySql v 5.6.36
For your issue there are three options:
Enable ON DELETE CASCADE.
But that is not an option in your case apparently
Disable foreign_key_checks before running your query, and re-enable it afterwards
Run two queries; first deleting referencing rows (ref_a, ref_b), then the rows in test
Otherwise you this will not be possible, that's what foreign keys are for; to ensure data consistency.
Related
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.
I have a self-referencing foreign-key constraint on my table. Because I'm transforming the schema, I'd like to copy the existing data into a new table with (more or less) the same structure:
CREATE TABLE test(
id INT NOT NULL PRIMARY KEY,
parent INT,
FOREIGN KEY (parent) REFERENCES test(id)
);
CREATE TABLE copy(
id INT NOT NULL PRIMARY KEY,
parent INT,
FOREIGN KEY (parent) REFERENCES copy(id)
);
However, when inserting the data:
INSERT INTO copy(id, parent) SELECT id, parent FROM test;
MySQL gives me the common integrity error:
Error Code: 1452. Cannot add or update a child row:
a foreign key constraint fails (`test`.`copy`, CONSTRAINT `copy_ibfk_1`
FOREIGN KEY (`parent`) REFERENCES `copy` (`id`))
It seems that MySQL checks the constraint after inserting each row instead of checking it after the whole insert. The exact same example works fine in PostgreSQL.
Is there any other way to insert this data or am I stuck with doing this in two steps like this?
INSERT INTO copy(id) SELECT id FROM test;
UPDATE copy
JOIN test ON test.id = copy.id
SET copy.parent = test.parent;
You can use
SET FOREIGN_KEY_CHECKS=0;
before your INSERT and
SET FOREIGN_KEY_CHECKS=1;
after to disable the check of the foreign key constraint, so you don't have to worry about the order of the inserts:
See the documentation to foreign_key_checks
foreign_key_checks
If set to 1 (the default), foreign key constraints for InnoDB tables
are checked. If set to 0, such constraints are ignored. [...] Typically
you leave this setting enabled during normal operation, to enforce
referential integrity. Disabling foreign key checking can be useful
for reloading such tables in an order different from that required by
their parent/child relationships. See Section 14.6.6, “InnoDB and
FOREIGN KEY Constraints”. [...]
Note
Setting foreign_key_checks to 1 does not trigger a scan of the
existing table data. Therefore, rows added to the table while
foreign_key_checks = 0 will not be verified for consistency.
CREATE TABLE test(
id INT NOT NULL PRIMARY KEY,
parent INT,
FOREIGN KEY (parent) REFERENCES test(id)
);
CREATE TABLE copy(
id INT NOT NULL PRIMARY KEY,
parent INT,
FOREIGN KEY (parent) REFERENCES copy(id)
);
INSERT INTO test(id, parent) VALUES(1, null);
INSERT INTO test(id, parent) VALUES(2, 1);
INSERT INTO test(id, parent) VALUES(3, null);
INSERT INTO test(id, parent) VALUES(4, 2);
UPDATE test SET parent=3 WHERE id=1;
SET FOREIGN_KEY_CHECKS=0;
-- Success with MySQL
INSERT INTO copy(id, parent) SELECT id, parent FROM test;
SET FOREIGN_KEY_CHECKS=1;
Your updated fiddle: http://sqlfiddle.com/#!2/ae623/1
I have a problem during SQL generation of my database diagram from MySQL Workbench (UNIQUE constraints are added in every field from combined primary key).
I have following diagram: https://dl.dropboxusercontent.com/u/3843729/baza.png
Moreover, it has following properties set: https://dl.dropboxusercontent.com/u/3843729/indexes.png
SQL generated:
CREATE TABLE IF NOT EXISTS `test`.`User_has_Menu` (
`User_id` BIGINT UNIQUE NOT NULL,
`Menu_id` BIGINT UNIQUE NOT NULL,
PRIMARY KEY (`User_id`, `Menu_id`),
INDEX `fk_User_has_Menu_Menu1_idx` (`Menu_id` ASC),
INDEX `fk_User_has_Menu_User1_idx` (`User_id` ASC),
CONSTRAINT `fk_User_has_Menu_User1`
FOREIGN KEY (`User_id`)
REFERENCES `test`.`User` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_User_has_Menu_Menu1`
FOREIGN KEY (`Menu_id`)
REFERENCES `test`.`Menu` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
As you can see, 'User_id' and 'Menu_id' have UNIQUE keyword, so as a result I cannot insert single user_id (or menu_id) in two rows, for example:
insert into user_has_menu (user_id, menu_id) values (1,1);
insert into user_has_menu (user_id, menu_id) values (1,3);
Second insert statement is not executed as user_id must be unique.
Note: If I create new diagram in MySQL Workbench, everything is working fine and the SQL generated is without problematic UNIQUE constraints.
How can I remove those constraints without creating new diagram?
first find the unique constraint names:
select *
from
information_schema.key_column_usage
where
and table_schema = 'my_database'
and table_name = 'my_table'
then drop them
alter table my_table drop index my_contraint
And because unique constraints are handled as indexes on MySQL you can try make sure you don't have these indexes on the MySQL graphical interface.
I have a table with a natural key and another with a foreign key constaint to it:
create table A
(
id varchar(255) not null primary key
...
)
create table B
(
a_id varchar(255) not null
...
foreign key (a_id) references A (id)
)
I would like to execute a transformation on A.id, (in this specific case lowercasing it) and simulataneously on B.a_id.
Obviously if I do:
update A set id=lower(id);
update B set a_id=lower(a_id);
Than I will get a foreign key constraint violation on the first update.
Is there anyway to execute the two updates "simultaneously", or can you recommend another way to deal with this?
Simplest Approach might be to Drop the constraint,
Perform Update Queries
Again, Introduce the Foreign Key Constraint.
drop the constraint and re-create the constraint with ON UPDATE CASCADE
then execute the update stament on the parent table no child table would get modified.
ALTER TTABLE b ADD CONSTARINT fk_const
FOREIGN KEY(a_id) REFERENCE a (id) ON UPDATE CASCADE
now execute this update
update A set id=lower(id);
I have set foreign key integrity in a table. But i am able to delete data from the master table, which is reference in child table..
What would be the problem
Actually it should say error on deletion like all referenced table data has to be deleted.
Did you specify ON DELETE CASCADE ? when you created your FK? Don't know which engine you are using either
example
CREATE TABLE parent (id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE child (id INT, parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id) REFERENCES parent(id)
ON DELETE CASCADE
) ENGINE=INNODB;
More here http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
mysql dont do it for you ,
you need declare trigger on delete action
before delete trigger example :
http://www.java2s.com/Code/Oracle/Trigger/Createabeforedeletetrigger.htm