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.
Related
I have to cooperate with an old school programmer. A long time ago he set up MySQL database. When he created it, he used his primary language as a language for naming tables, columns etc.
Now I would like to have a relation graph for this database and I need it for Prisma to figure out relations between tables, thus I would like to add foreign keys, but I cannot add them easily as he does violate them.
I suppose the easiest thing to do would be to disable foreign key check SET foreign_key_checks = 0;, but this only ever lasts session. Is there a way around this?
Can I do something SET foreign_key_checks = 0;, but for every connected user, and ideal after DB restart too?
https://dev.mysql.com/doc/refman/8.0/en/set-variable.html
Sets it only current session, even same user upon next reconnect won't have this setting.
SET [SESSION] key = value (SESSION is default and thus optional)
Sets it to all users, till next restart of MySQL server happens.
SET GLOBAL key = value
Same as global, but will also apply after restart. This will, in fact, change the config file of the MySQL server.
SET PERSIST key = value (PERSIST is only available since v8)
There is also PERSIST_ONLY which will apply the effect only after a restart.
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).
Error 1217: Cannot delete or update a parent row: a foreign key constraint fails
SQL Statement: drop table s_a_user.main
i used "rpl -Ris ..." to check the sql dumps, and it's not in there. i queried the information schema, and it's not in there either. i think this is a bug, but i may just not be finding an elusive reference to this table. screenshot below shows all info needed.
http://tinypic.com/r/30lcu2t/6 - they resized it and it's hard to read, but the tables listed are s_a_user.resume, not s_a_user.main, so, in other words, it confirms there is nothing referencing this
==UPDATE==SOLVED==
this is a bug in mysql. "SHOW ENGINE INNODB STATUS" shows the error came from "s_a_mail.topic", which does not even exist [-_-] ...
to solve this: delete all innodb log files, delete the schema, delete the schema's directory, restart mysql with innodb_force_recovery=4 in your my.conf, remove the force recovery, restart mysql again, recreate the database schema, reimport the data backup, restart mysql with innodb_force_recovery=4 AGAIN, take out innodb_force_recovery=4 and restart AGAIN.
this fixes the foreign key problem, but now workbench crashes when accessing the s_a_user schema's tables, so now i get to investigate that... [-_-] i'm about to just build a new database system...
SET FOREIGN_KEY_CHECKS=0; DROP TABLE ´your_table´; SET FOREIGN_KEY_CHECKS=1;
This should help you.
Trick from Rune Kaagaard on this question
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;
In my process, I do something like:
SET FOREIGN_KEY_CHECKS = 0;
LOAD DATA INFILE '/path/to/mytable.txt' INTO TABLE mytable;
SET FOREIGN_KEY_CHECKS = 1;
Now, I need to check that the data after this import is not breaking the referential integrity. I would like to do something like
check database all foreign_keys;
Is a similar command exists? If not, how to do this control?
Environment: MySQL v5.1.xx with InnoDB
Thanks
Answer
Here is some code which does what you need. It looks like there's no such command.
History
OK, I'm not a MySQL expert but referential integrity is managed constantly unless you disable it. You cannot insert a row into a table which violates a constraint unless you've dropped or disabled the constraint first. There's no need to "check" them.
If you did "disable" them, then enabling them will force a check.
This is in fact completely wrong and very scary indeed.
at least in 5.1
I think if they had that function, they would just call it when you re-enabled the constraints, so I doubt you'll find it in the server.
The above link is dead, sadly.
The script mentioned in this blog post does a nice job of showing FKs which aren't referenced (though it will also show them when the FK is nullable, so may be legitimately null, so not always helpful!):
http://www.mysqlperformanceblog.com/2011/11/18/eventual-consistency-in-mysql/