Disable mysql foreign key check for specific tables - mysql

Is it possible to disable the Mysql foreign key check for specific tables?

Basically there is not built-in functionality for that in MySQL.
You are able to disable FKs - as you may know - but not for a specific tables - but all.
Below is an example how it works only for a session (from MySQL 5.xx you can do it globally).
SET FOREIGN_KEY_CHECKS = 0; #Off
SET FOREIGN_KEY_CHECKS = 1; #On
But you could handle this in a different way - with stored procedures.
In theory you could build stored procedure that drop foreign keys from particular tables, save all this (ie table, FK name, references) to a table so you could retrieve all that later and based on that re-create the same FKs you had before.
But the question here is also about timing - for how long you would like to make them disabled- and primary what is reason behind (some big data inserts, updates, deletions etc).

Related

"Set foreign_key_checks= 0;" but only for one database

I have an umbrella MySQL server with many databases. I'd like to disable foreign keys for all tables in only one database. However the usual command disables foreign keys for all databases.
Is there a way for it to work in the scope of only one database?
Also, I'd like it to work not per session. But for session-wise globally.
No. The variable applies to all foreign keys on the MySQL instance. There is no way to limit it to the scope of one schema.
The only solutions are the ones you already know:
set foreign_key_checks=0 as a session variable, only for sessions that will access the schema you have in mind.
Drop foreign key constraints in the tables of the schema you have in mind.
Host the schema in a separate MySQL instance.

Which is the better, dropping and recreating FK constraints OR Disabling and enabling FK checks?

I have few columns in various tables of MYSQL database which were allocated more length than actually needed. So now I try to make them of proper length. They were VARCHAR(64) and I want to make them CHAR(36). Those columns are involved in Foreign Keys. These changes are going to be a new SQL file, which is run with Flyway Engine. Which of the two options is better?
1) drop the constraints and modify columns and recreate constraints.
2) execute set foreign_key_checks=0, alter columns and execute set foreign_key_checks=1.
Since you are going to change the length its better to disable foreign_key_checks. Because it will affect only your current session (unless you mention global). so that it will not affect other session which depends on foreign key.

Clarification required for the 'Disable foreign key checks' option

I'm looking for some clarification on a statement from the MySQL docs
I intend to export a DB with the Disable foreign key checks option selected, as doing it without causes an error when I import the DB. However, after reading the docs I'm left with two questions with regard to importing the DB -
Will foreign_key_checks be set back to 1 automatically after the import for that DB, or do I have to do it manually?
will the Foreign Keys already in place when the DB was exported still be valid?
The relevant part of the docs reads as below, which to me is not particularly clear -
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.
http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html
See the big table at the start. foreign_key_checks setting is session based. You do not have to reset it back to 1 yourself. (Although it doesn't hurt.)
Yes. No actual relations or constraints will be affected. Only the checking of those constraints during the time when the checks are off.

Restore DB from SQL script with Foreign Key Constraints

I am trying to restore a DB using an SQL script, but things foreign key constraints get in the way
I am taking a MySQL DB and bringing it over to PostgreSQL.
Since the MySQL create table syntax ended up being quite different, I took another PostgreSQL DB with the same schema, but different data and restored the schema only, from that.
In other words, I now have a database with tables, constraints, sequences and all that shnaz but no data inside.
So, it's is time to restore data.
I take a backup of the MySQL DB with phpMyAdmin (data only) as an SQL script (pgAdmin does not seem to accept zip or gzip files for some reason) and run the SQL script.
Now, this is where the problems start to happen, it's only natural, I am going from MySQL to PostgreSQL, so syntax errors are bound to happen.
But, there are other non syntax related problems to, like this one:
ERROR: insert or update on table "_account" violates foreign key constraint "fk_1_account"
DETAIL: Key (accountid)=(2) is not present in table "_entity".
So, yeah, basically, a foreign constraint exists, the query is trying to insert data into the _account table, but the corresponding data has not been inserted into the _entity table yet.
How do I get around that? Is there a way to make pgAdmin3/PostgreSQL disable ALL OF the constraints, insert the data, and then re-enable the constraints?
A syntax related error I encountered, was this one:
INSERT INTO _accounttype_seq (id) VALUES (11);
The PostgreSQL equivalent of that statement (if I am correct) is
ALTER SEQUENCE _accounttype_seq INCREMENT BY 11;
But, it's a bit of a pain to run through the whole script and change all 200+ Sequence insert statements. So, I am being lazy here, but is there an easier way to deal with the sequences as well?
Or, do you guys have any suggestions for a different set of tools to make this easier?
Thanks for your time, have a good day.
Do not try to get around the foreign key constraints. That is the way to make sure the data is bad.
First look at the constraints and make sure you are inserting to the tables in the correct order. If _entity is parent of "_account, then it should be populated first.
Next you need to have the script move any failing records to an exception table. Then you can look at them and see what the data integrity issues is and if you need to throw the records away permanently or try to figure out what the missing parent value should be. If it is critical data such as orders where the customer no longer exists (possible in any system that didn't have correct fks to begin with) and you must keep the record and cannot determine what the parent value should have been, you can create an 'Unknown" record in the customer table and assign all bad orders to that customer id.
And manually changing the alter sequences shouldn't take long even if it is boring. There wil be plently of other things you need to handle manually in a conversion of this type.
I would try to find a data import tool for PostgreSQL - I live in SQL server world where I would use SSIS but you need the equivalent of SSIS for the PostgreSQL world.
Aparently the foreign keys weren't actually enforced in MySQL (maybe because of using MyISAM) or the generated SQL just does it in the wrong order.
If it's "only" the wrong order, I see two possible solutions:
edit the generated script and either move all FK definitions to the end of the script
Edit the definition of each FK constraint and set them all to initially deferred. Then run the script as one single transaction with only on commit at the very end.
Edit (because this is too much to be put as a comment)
Using SET CONSTRAINTS ALL DEFERRED will only work if the constraints have been created with the option DEFERRABLE.
To run everything in one single transaction, you have to make sure you have turned autocommit off. Then simply run the INSERTs and at the very end issue a COMMIT. A ; will only commit if you have autocommit on.
If you want to be independent of the autocommit setting, then start your script with [BEGIN][1] and make sure there is only a single COMMIT at the very end.
BEGIN DEFERRABLE
INSERT INTO table_one ... ;
INSERT INTO table_two ... ;
.....
COMMIT;

Foreign key in SQL Server 2008 pointing to another database

How can I add a constraint that references a foreign column from another database?
Some time ago I read that it can be done with linked server and others say with triggers. What's the preferred way of doing this if that's possible at all?
Thanks!
Linked servers will not work.
FK's must point to local tables.
The preferred way is not to do this, though you can pull a few hacks to make it happen.
For example you could have triggers cause the reference to be created/checked but I wouldn't consider that equivalent to a FK constraint.
Related question:
Can you have a Foreign Key onto a View of a Linked Server table in SQLServer 2k5?
Use an instead of trigger (you may or may not need linked servers depending on whether the other database is on a differnt server). Make sure the trigger can handle multiple row inserts/updates/deletes. I'd also suggest moving the records that fail the check to an exception table.
Foreign keys cannot go across database boundaries. If you try to do this, you'll get:
Msg 1763, Level 16, State 0, Line 1
Cross-database foreign key
references are not supported. Foreign key ***
Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.
If you need to enforce some kind of relationship between two separate databases, then yes - you might need a linked server (if that second database is on a second server), and possibly triggers - but all of those things will be very hard to get right, very inefficient and very error prone.
One way you might be able to do this would be data replication - replicate the table you want to reference into your source database, and then establish a foreign key relationship with that replicated table. But that will never be quite "live" and "real-time" - there will also be a bit of a lag in the data replication.