mysql delete and foreign key constraint - mysql

I'm deleting selected rows from both table in MYSQL, the two tables have foreign keys.
DELETE d,b
FROM A as b
INNER JOIN B as d on b.bid=d.bid WHERE b.name LIKE '%xxxx%';
MYSQL complains about foreign keys even though I'm trying to delete from both tables:
Error: Cannot delete or update a parent row: a foreign key constraint
fails (`yyy/d`, CONSTRAINT `fk_d_bid` FOREIGN KEY (`bid`) REFERENCES
`b` (`bid`) ON DELETE NO ACTION ON UPDATE NO ACTION)
what's the best solution here to delete from both table?

Change this constraint to use ON DELETE CASCADE -- which means that if a row is deleted, then any "child" rows will be automatically deleted as well.
Of course take good care of using CASCADE -- only use it when necessary. If you're overzealous with it, and accidentally do a well-placed DELETE, it might end up deleting half of your database. :)
See documentation on foreign key constraints.

I think I see what you're trying to do
If you can't change the table structure, then you could use 2 statements, the first with a sub-select
delete from B where bid IN (select bid from A where name like '%xxxx%');
delete from A where name like '%xxxx%';

Related

How do I correct this ('Cannot delete or update a parent row')?

mysql> delete from faculty where fid in ( select fid from class);
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign
key constraint fails (ass1.class, CONSTRAINT class_ibfk_1
FOREIGN KEY (fid) REFERENCES faculty (fid))
This is throwing the mentioned error. What should I do?
It is dangerous to force this without knowing what the consequences are.
This error is happening because there is another table that has a foreign key association with something you're trying to delete. What do you want to happen to those rows in other tables that rely on the deleted data? Here are a few options:
If you want to delete those rows that rely on the data you're trying to delete, look into cascade deletion.
If you decide the data that relies on the data you need to delete should no longer have a foreign key constraint, you can drop the constraint.
If you don't want either of these things, consider not actually deleting your data, but instead using a boolean column to flag rows as "inactive". Then, you can filter on the flag when retrieving data if needed, while still maintaining old records that rely on that "obsolete" data.
You're trying to delete from parent table. Which is probably why you're getting an error.
Either set up the FK to cascade deletes:
YourForeignIDField INT NOT NULL REFERENCES ParentTable.ID ON UPDATE CASCADE ON DELETE CASCADE
Or set up the foreign ID to accept Nulls and cascade to null:
YourForeignIDField INT NULL REFERENCES ParentTable.ID ON UPDATE CASCADE ON DELETE SET NULL
Or delete all children first:
DELETE FROM ChildTable WHERE ForeignID = YourForgeignID;
DELETE FROM ParentTable WHERE ID = YourID;

MYSQL Foreign Key ON DELETE and ON UPDATE

I have a website which has a users table and a movies table. I am creating a favourites table so that users can save movies to their favourites list. The question is concerning the favourites table which I have been adviced to use the below :
CREATE TABLE Favorites (
user_id INT NOT NULL,
movie_id INT NOT NULL,
PRIMARY KEY (user_id, movie_id),
FOREIGN KEY (user_id) REFERENCES Users(user_id),
FOREIGN KEY (movie_id) REFERENCES Movies(movie_id)
);
I noticed when reading about foreign keys there is an 'ON DELETE' and 'ON UPDATE' option where you can set to restrict, cascade etc...
If a user has favourited many movies, and then one of the movies is deleted from the movie table, what would happen if it the foreign key was set to "CASCADE"? would any rows from the favourites table be deleted also? What would happen if the foreign key was set to "RESTRICT"?
I am just after a basic explanation as I do not currently fully understand this.
13.1.17.3 Using FOREIGN KEY Constraints
...
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. Between two tables, do not define several ON UPDATE CASCADE clauses that act on the same column in the parent table or in the child table.
Note
Currently, cascaded foreign key actions do not activate triggers.
...
RESTRICT: Rejects the delete or update operation for the parent table. Specifying RESTRICT (or NO ACTION) is the same as omitting the ON DELETE or ON UPDATE clause.
NO ACTION: A keyword from standard SQL. In MySQL, equivalent to RESTRICT. The MySQL Server rejects the delete or update operation for
the parent table if there is a related foreign key value in the
referenced table. Some database systems have deferred checks, and NO
ACTION is a deferred check. In MySQL, foreign key constraints are
checked immediately, so NO ACTION is the same as RESTRICT.
...

SQL: Cannot delete or update parent row: a foreign key constraint fails

Whenever I try to delete a survey from table "survey" like this:
DELETE FROM surveys WHERE survey_id = 77
It prompts me an error stated below:
#1451 - Cannot delete or update a parent row: a foreign key constraint fails ('user_surveys_archive', CONSTRAINT
'user_surveys_archive_ibfk_6' FOREIGN KEY ('user_access_level_id')
REFERENCES 'user_surveys' ('user_access_level_id') ON DELETE NO ACTION
)
First thing: I do not have any such table with this name "user_surveys_archive_ibfk_6"
2nd thing: There is no record of this survey in other tables.
Any idea on how can I delete this record of fix this issue?
Edit
This is the line I found when I export the table Constraints for table surveys
ALTER TABLE `surveys`
ADD CONSTRAINT `surveys_ibfk_1` FOREIGN KEY (`survey_type_id`) REFERENCES `survey_types` (`survey_type_id`) ON DELETE CASCADE ON UPDATE NO ACTION;`
You will need to first remove or update some rows in table user_surveys_archive.
Those rows are related to rows in the user_surveys table.
Likely, there's a foreign key constraint defined on table user_surveys that references rows in surveys you are attempting to delete.
(You'd need to check the foreign key definition, quickest way to get that is a
SHOW CREATE TABLE user_surveys
And look for REFERENCES surveys. (Likely, its a column named survey_id, but we're just guessing without looking at the definitions of the foreign key constraints.)
To find the rows in user_surveys_archive that are preventing the DELETE from happening...
SELECT a.*
FROM user_surveys_archvive a
JOIN user_surveys u
ON u.user_access_level_id = a.user_access_level_id
JOIN surveys s
ON s.survey_id = u.survey_id -- change this to whatever the FK is
WHERE s.survey_id = 77
It's likely that the foreign key constraint from user_surveys to surveys is defined with ON DELETE CASCADE. The attempt to delete rows from surveys identifies rows in user_surveys that should automatically be removed.
The attempt to automatically remove the rows from user_surveys is what's violating the foreign key constraint defined in user_surveys_archive. And that foreign key is not defined with ON DELETE CASCADE.
(The other possibility is that there's a trigger defined that's doing some DML operations, but that would be odd.)
Once you identify the rows, you need to decide what changes to make to allow you to remove rows from surveys.
You can either DELETE the rows, or UPDATE them.
To delete the rows from user_surveys_archive, modify the query above and replace SELECT with DELETE. If the user_access_level_id column in user_surveys_archive allows for NULL values, you can do an update.
Replace SELECT a.* FROM with UPDATE, and add SET a.user_access_level_id = NULL on a line above the WHERE clause...
UPDATE user_surveys_archvive a
JOIN user_surveys u
ON u.user_access_level_id = a.user_access_level_id
JOIN surveys s
ON s.survey_id = u.survey_id -- change this to whatever the FK is
SET a.user_access_level_id = NULL
WHERE s.survey_id = 77
(It seems strange to me that name of the foreign key column is user_access_level_id. But its just a column name, it could be named anything... seems odd to me because of the conventions and patterns that we follow in naming foreign key columns.)
You should allow the foreign key to be NULL and then choose ON DELETE SET NULL.
Personally I would recommend using both "ON UPDATE CASCADE" as well as "ON DELETE SET NULL" to avoid unnecessary complications, however your setup may dictate a different approach.
Hope this helps.
The survey_id of 77 must be referenced in a table possibly named user_surveys_archive. The error is saying the name of the foreign key restraint which is the user_surveys_archive_ibfk_6. If you need to delete survey_id = 77 you will have to delete any child records or other records that reference it as a foreign key.
Edit After posting my answer I saw the comments above. atif the foreign key in the user_surveys_archive table may be named differently but still equal the value of 77 that you are trying to delete, and/or be referencing the survey_id. If that is not the case then there are some other problems within the database. You could try and look at the code for the FK to see how it was made and what fields it is referencing, or run a query to see if there are any records in the user_surveys_archive where the user_access_level_id is = 77.
Edit 2 spencer7593's answer lays out how to run some of the queries mentioned in my answer.

Unable to delete a record from self indexed db object

I am not able to delete a row from a database object. In my case db object is having self indexing.
A field root_id is having a foreign key relation with key_id (Primary key). The referential integrity is designed as ON UPDATE NO ACTION AND ON DELETE NO ACTION. Even still I am not able to delete.
CONSTRAINT `fk_MyTab` FOREIGN KEY (`root_id`) REFERENCES `MyTab` (`key_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
I have to delete records from this table WHERE key_id = root_id.
When I try to delete I am getting the following.
Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint fails (`MyTab`, CONSTRAINT `fk_MyTab` FOREIGN KEY (`root_id`) REFERENCES `MyTab` (`key_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
Point me to the right direction.
That is what NO ACTION does, it prevents deletion of a row with any child rows. If you want to delete the children too, use CASCADE.
You could also preserve the data by setting it to ON DELETE SET NULL, in which case if the parent is deleted the child rows will have their foreign key column set to null.
I think this is a good practice to do when you're designing a database that has lots of foreign keys. If you have tables with ON DELETE CASCADE option which are linked with other field to other tables, the delete cascade option will fail (because mysql could not delete in the same order you create the tables)". A solution for this case is to declare a clause ON DELETE SET NULL in the others foreign keys

Delete a Primary Key Without Affecting Foreign Key Constrain to Other Table

I want to delete a record from a school table without affecting a foreign key to the department name. I tried but I got this message:
"Cannot delete or update a parent row: a foreign key constraint fails
(arusms.department, CONSTRAINT department_ibfk_1 FOREIGN KEY
(school_name) REFERENCES school (school_name) ON UPDATE
CASCADE)"
I'm not sure why you would want to do that. If you delete the school, the department will be orphaned. That's the point of having foreign keys in the first place, to enforce referential integrity. If you want the department to remain and to be able to do this, you will need to alter the foreign key to include ON DELETE SET NULL. Otherwise, you will have to drop the constraint, perform the delete, and recreate the constraint.
Your error message is hiding the real cause.
(
arusms.department,
CONSTRAINT department_ibfk_1
FOREIGN KEY (school_name)
REFERENCES school (school_name)
ON UPDATE CASCADE
)
When you created the foreign key constarint, you omitted the ON DELETE part. MySQL used the default action for this, which is ON DELETE RESTRICT. See the MySQL docs: FOREIGN KEY Constraints
If you want to be able to delete schools without cascading effect to the related departments, you can either
remove the FK constraint or
make the column (department.school_name) nullable and alter the constraint to have the ON DELETE SET NULL action.
If you want to be able to delete schools and cascading deleting the related departments, you can
alter the constraint to have the ON DELETE CASCADE action.
The whole purpose of having a foreign key is to keep data consistent. In your case, it means that for each department, there must exist a corresponding school record. And if you DELETE a school, all corresponding departments should be deleted as well, or at least their school reference must be NULLed.
If you don't need this kind of enforcement, DROP the foreign key.
Alternatively, if you just want to reassign a department to another school, first do that, and only then DELETE the original school.