860

Is it possible to temporarily disable constraints in MySQL?

I have two Django models, each with a foreign key to the other one. Deleting instances of a model returns an error because of the foreign key constraint:

cursor.execute("DELETE FROM myapp_item WHERE n = %s", n)
transaction.commit_unless_managed()  #a foreign key constraint fails here

cursor.execute("DELETE FROM myapp_style WHERE n = %s", n)
transaction.commit_unless_managed()

Is it possible to temporarily disable constraints and delete anyway?

8
  • 4
    Either I don't get what you want to do, or what you are trying to do is very, very, very ugly. Even if you can do it, you probably shouldn't. Commented Mar 19, 2013 at 14:06
  • 3
    Dropping and reapplying an FK is changing your db. You're trying to defy the very constraints that allow the system to see some sense, it has no regard that an FK could be a temporary thing, and if it did know, it would panic. Commented Mar 19, 2013 at 14:07
  • 1
    Its strange what you trying to do. But which database are you using? Commented Mar 19, 2013 at 14:08
  • 5
    what if, instead of disabling your constraint, you permanently modified it to ON DELETE SET NULL? That would accomplish a similar thing and you wouldn't have to turn key checking on and off. Commented Mar 19, 2013 at 14:15
  • 1
    @dnagirl: that would be better, indeed. How can I do that? Commented Mar 19, 2013 at 14:20

9 Answers 9

1848

Try DISABLE KEYS or

SET FOREIGN_KEY_CHECKS=0;

Make sure to

SET FOREIGN_KEY_CHECKS=1;

after.

Sign up to request clarification or add additional context in comments.

10 Comments

is this something that is set for mysql as a whole or just that session?
I believe it is per session.
Can I just disable FOREIGN_KEY_CHECKS for a single table?
To clarify @Pacerier's comment: For Innodb, you cannot DISABLE KEYS. But you can accomplish what is requested in this question, using the other command shown: SET FOREIGN_KEY_CHECKS=0; (I thought at first he was saying there was no way to accomplish this.)
|
202

To turn off foreign key constraint globally, do the following:

SET GLOBAL FOREIGN_KEY_CHECKS=0;

and remember to set it back when you are done

SET GLOBAL FOREIGN_KEY_CHECKS=1;

WARNING: You should only do this when you are doing single user mode maintenance. As it might resulted in data inconsistency. For example, it will be very helpful when you are uploading large amount of data using a mysqldump output.

10 Comments

this is what I needed to know, so its not great practice, but this guys answer should be scoring higher...
This worked for me after trying the 'best answer' didn't work for me. Perhaps an explanation of the difference could be added.
@hexnet The difference is that just SET FOREIGN_KEY_CHECKS just changes the value for the current connection, while SET GLOBAL .. changes the value for all connections, including future connections. If you just do SET FOREIGN.. in one window, then try to apply the statement in a different window (over a different connection), the value has not changed there. With GLOBAL, the same variable has the same value for both connections.
The only thing that could help me when playing back a larger dump (6+ GB) <3
This doesn't work for me. When I try, I see:ERROR 1228 (HY000): Variable 'foreign_key_checks' is a SESSION variable and can't be used with SET GLOBAL
|
81

I normally only disable foreign key constraints when I want to truncate a table, and since I keep coming back to this answer this is for future me:

SET FOREIGN_KEY_CHECKS=0;
TRUNCATE TABLE table;
SET FOREIGN_KEY_CHECKS=1;

Comments

33

To turn off the foreign key constraint globally:

SET GLOBAL FOREIGN_KEY_CHECKS = 0;

And for the active foreign key constraint:

SET GLOBAL FOREIGN_KEY_CHECKS = 1;

1 Comment

This appears to be an exact duplicate of an existing, older answer from @berniey
29

Instead of disabling your constraint, permanently modify it to ON DELETE SET NULL. That will accomplish a similar thing and you wouldn't have to turn key checking on and off. Like so:

ALTER TABLE tablename1 DROP FOREIGN KEY fk_name1; //get rid of current constraints
ALTER TABLE tablename2 DROP FOREIGN KEY fk_name2;

ALTER TABLE tablename1 
  ADD FOREIGN KEY (table2_id) 
        REFERENCES table2(id)
        ON DELETE SET NULL  //add back constraint

ALTER TABLE tablename2 
  ADD FOREIGN KEY (table1_id) 
        REFERENCES table1(id)
        ON DELETE SET NULL //add back other constraint

Have a read of this (http://dev.mysql.com/doc/refman/5.5/en/alter-table.html) and this (http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html).

2 Comments

Beware alterting table can take a long time, better to set the server global for FOREIGN_KEY_CHECKS to 0 and put it back once the dirty work is done. Besides it might lock for writing your tables.
Won't that break the reference when altering the remote column type? (It seems my client renames a modified temp table to the original table name.)
14

For me just SET FOREIGN_KEY_CHECKS=0; wasn't enough. I was still having a com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException.

I had to add ALTER TABLE myTable DISABLE KEYS;.

So:

SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE myTable DISABLE KEYS;
DELETE FROM myTable;
ALTER TABLE myTable ENABLE KEYS;
SET FOREIGN_KEY_CHECKS=1;

2 Comments

FYI, mySQL 5.7 throws warning, InnoDB engine doesn't have this option when running DISABLE KEYS command.
this did work, without the alter table it also didn't work for me
13

A very simple solution with phpMyAdmin:

  • In your table, go to the SQL tab
  • After you edit the SQL command that you want to run, there is a check box next to GO, named 'Enable foreign key checks' .
  • Uncheck this check box and run your SQL. It will be automatically rechecked after executing.

1 Comment

Thanks! Indeed solution SET FOREIGN_KEY_CHECKS=0; ..... SET FOREIGN_KEY_CHECKS=1; didn't work for me in PHPMyAdmin because I forgot to uncheck the 'Enable foreign key checks' checkbox. In PHPMyAdmin you can skip these SET commands and just uncheck the checkbox.
7

In phpMyAdmin you can select multiple rows and can then click the delete action. You'll enter a screen which lists the delete queries. It looks like this:

enter image description here

Please uncheck the "Enable foreign key checks" checkbox, and click on Yes to execute them.

This will enable you to delete rows even if there is an ON DELETE restriction constraint.

Comments

3

If the key field is nullable, then you can also set the value to null before attempting to delete it:

cursor.execute("UPDATE myapp_item SET myapp_style_id = NULL WHERE n = %s", n)
transaction.commit_unless_managed() 

cursor.execute("UPDATE myapp_style SET myapp_item_id = NULL WHERE n = %s", n)
transaction.commit_unless_managed()

cursor.execute("DELETE FROM myapp_item WHERE n = %s", n)
transaction.commit_unless_managed()

cursor.execute("DELETE FROM myapp_style WHERE n = %s", n)
transaction.commit_unless_managed()

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.