Disabling foreign key checks on the command line - mysql

I have a backup script for my MySQL database, using mysqldump with the --tab option so it produces a .sql file for the structure and a .txt file (pipe-separated) for the content.
Some tables have foreign keys, so when I import it I'm getting the error:
ERROR 1217 (23000) at line 8: Cannot delete or update a parent row: a foreign key constraint fails
I know about using SET FOREIGN_KEY_CHECKS=0 (and SET FOREIGN_KEY_CHECKS=1 afterward). If I add those to each .sql file then the import works. But then obviously on the next mysqldump those get overwritten.
I also tried running it as a separate command, like below but the error comes back:
echo "SET FOREIGN_KEY_CHECKS=0" | mysql [user/pass/database]
[all the imports]
echo "SET FOREIGN_KEY_CHECKS=1" | mysql [user/pass/database]
Is there some other way to disable FK checks on the command line?

You can also use --init-command parameter of mysql command.
I.e.: mysql --init-command="SET SESSION FOREIGN_KEY_CHECKS=0;" ...
MySQL 5.5 Documentation - mysql options

You can do this by concatenating the string to the file inline. I'm sure there's an easier way to concatenate strings and files, but it works.
cat <(echo "SET FOREIGN_KEY_CHECKS=0;") imports.sql | mysql
I don't think you need to set it back to 1 since it's just one session.

Login to mysql command line:
mysql -u <username> -p -h <host_name or ip> Then run
1 SET FOREIGN_KEY_CHECKS=0;
2.use <database_name>
3 SOURCE /pathToFile/backup.sql;
4 SET FOREIGN_KEY_CHECKS=1;
5 exit

Just another one to do the same:
{ echo "SET FOREIGN_KEY_CHECKS=0;" ; cat imports.sql ; } | mysql

Another way with .gz files:
gunzip < backup.sql.gz | mysql --init-command="SET SESSION FOREIGN_KEY_CHECKS=0;" -u <username> -p

Based off the comments and answers, I ended up using this for a zipped database import with both InnoDB and MyISAM:
{ echo "SET FOREIGN_KEY_CHECKS=0;SET UNIQUE_CHECKS=0;" ; zcat dump.gz ; } | mysql

Simply, you can call any command from cmd, this way:
mysql -e "SET SESSION FOREIGN_KEY_CHECKS=1;"
Of course, you need to specify the username, password and host using -u, -p and -h

Related

Restoring mysql backup through windows batch file, which calls the .sql file

Im trying to restore a mysql database from a back up. I was able to do it on command prompt directly using
mysql> -u username -ppassword < E:\replication\DestinationTest\restore.sql.
This worked fine.
I'm trying to put the same line in a .txt file, along with other mysql statements and call that. txt file from mysql command prompt.I have few delete staments and then the restore statement in the .txt file.
It looks like this :
enter code here
Delete from Db.tbl1;
Delete from Db.tbl2;
Delete from Db.tbl3;
Delete from Db.tbl4;
Delete from Db.tbl5;
-h Server -D DB -u username -ppassword < E:\replication\DestinationTest\Db.sql;
When i call this above .txt file from mysql prompt, it executes the delete statements but errors out on the restore part. It says Unknown database 'ereplicationdestinationtestdb.sql'.
Please let me know , what is the right way to do it.
Your delete statements are executing since each table is preceded by schema name like below.
Delete from Db.tbl1;
Delete from Db.tbl2;
But please confirm if you have missed schema name to which the tables needed to be restored ? As per error you mentioned, It seems your restore.sql does not knows into which schema the tables need to be imported.
This is a "prompt, not a command:
mysql>
So this is invalid:
mysql> -u username -ppassword < E:\replication\DestinationTest\restore.sql.
Also, the period at the end is probably a typo.
This would be a potentially valid line in a batch file:
mysql -u username -ppassword < E:\replication\DestinationTest\restore.sql
If you want to do some other things in the batch file, then first build a text file with SQL statements, such as
Delete from Db.tbl1;
Delete from Db.tbl2;
Delete from Db.tbl3;
Delete from Db.tbl4;
Delete from Db.tbl5;
Put nothing else in that file. Let's call the files deletes.sql. Now, we will put the two together -- two lines:
mysql -u username -ppassword < E:\replication\DestinationTest\restore.sql
mysql -u username -ppassword < deletes.sql
PS: TRUNCATE TABLE Db.tbl4; runs faster than DELETE if you just want to remove all the rows.

Errror 3554 while importing a .sql file

ERROR 3554 (HY000) at line 318: Access to system table 'mysql.innodb_index_stats' is rejected.
Operation failed with exitcode 1
11:27:20 Import of C:\Users\VELOXSHOP\Downloads\dumpfilename.sql has finished with 1 errors
How do I allow acess to that table?
You'll need to make a new dump/backup of your old database, this time remove those innodb tables from your target. You can do this by using --ignore-table parameter on the command line:
mysqldump -u root -p --all-databases --ignore-table=mysql.innodb_index_stats --ignore-table=mysql.innodb_table_stats > dump.sql
Then you should be able to restore your backup on the new database using the command below:
mysql -u root -p < dump.sql
You can also circumvent this error using the --force option which causes mysql client to continue despite errors.
Try to add -f to your command like so:
mysql -u root -p -f < dump.sql
-f means --force.
This did the trick for me!
It seems to be restricted in Mysql 8. Remove the insert statement from the sql file. You may have to use sed if the file is very large
https://stackoverflow.com/a/26379517/1106420
https://bugs.mysql.com/bug.php?id=92675
That is a MySQL system table and it's unlikely that you should be inserting records into it directly. MySQL should update the table when it calculates new statistics for indexes when thresholds pass.
Inspect line 318 and figure out why it's trying to insert into that table.

Access denied; you need (at least one of) the SUPER privilege(s) for this operation

So I try to import sql file into rds (1G MEM, 1 CPU). The sql file is like 1.4G
mysql -h xxxx.rds.amazonaws.com -u user -ppass --max-allowed-packet=33554432 db < db.sql
It got stuck at:
ERROR 1227 (42000) at line 374: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
The actual sql content is:
/*!50003 CREATE*/ /*!50017 DEFINER=`another_user`#`1.2.3.4`*/ /*!50003 TRIGGER `change_log_BINS` BEFORE INSERT ON `change_log` FOR EACH ROW
IF (NEW.created_at IS NULL OR NEW.created_at = '00-00-00 00:00:00' OR NEW.created_at = '') THEN
SET NEW.created_at = NOW();
END IF */;;
another_user is not existed in rds, so I do:
GRANT ALL PRIVILEGES ON db.* TO another_user#'localhost';
Still no luck.
Either remove the DEFINER=.. statement from your sqldump file, or replace the user values with CURRENT_USER.
The MySQL server provided by RDS does not allow a DEFINER syntax for another user (in my experience).
You can use a sed script to remove them from the file:
sed 's/\sDEFINER=`[^`]*`#`[^`]*`//g' -i oldfile.sql
Remove the 3 lines below if they're there, or comment them out with -- :
At the start:
-- SET ##SESSION.SQL_LOG_BIN= 0;
-- SET ##GLOBAL.GTID_PURGED=/*!80000 '+'*/ '';
At the end:
-- SET ##SESSION.SQL_LOG_BIN = #MYSQLDUMP_TEMP_LOG_BIN;
Note that the comment characters are "dash dash space" including the space.
A better solution is to stop these lines from being written to the dump file at all by including the option --set-gtid-purged=OFF on your mysqldump command.
Another useful trick is to invoke mysqldump with the option --set-gtid-purged=OFF which does not write the following lines to the output file:
SET ##SESSION.SQL_LOG_BIN= 0;
SET ##GLOBAL.GTID_PURGED=/*!80000 '+'*/ '';
SET ##SESSION.SQL_LOG_BIN = #MYSQLDUMP_TEMP_LOG_BIN;
not sure about the DEFINER one.
When we create a new RDS DB instance, the default master user is not the root user. But only gets certain privileges for that DB instance. This permission does not include SET permission. Now if your default master user tries to execute mysql SET commands, then you will face this error: Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation
Solution 1
Comment out or remove these lines
SET #MYSQLDUMP_TEMP_LOG_BIN = ##SESSION.SQL_LOG_BIN;
SET ##SESSION.SQL_LOG_BIN= 1;
SET ##GLOBAL.GTID_PURGED=/*!80000 '+'*/ '';
Solution 2
You can also ignore the errors by using the -f option to load the rest of the dump file.
mysql -f <REPLACE_DB_NAME> -u <REPLACE_DB_USER> -h <DB_HOST_HERE> -p < dumpfile.sql
Just a MacOS extra update for hjpotter92 answer.
To make sed recognize the pattern in MacOS, you'll have to add a backslash before the = sign, like this:
sed -i old 's/\DEFINER\=`[^`]*`#`[^`]*`//g' file.sql
Problem: You're trying to import data (using mysqldump file) to your mysql database ,but it seems you don't have permission to perform that operation.
Solution: Assuming you data is migrated ,seeded and updated in your mysql database, take snapshot using mysqldump and export it to file
mysqldump -u [username] -p [databaseName] --set-gtid-purged=OFF > [filename].sql
From mysql documentation:
GTID - A global transaction identifier (GTID) is a unique identifier created
and associated with each transaction committed on the server of origin
(master). This identifier is unique not only to the server on which it
originated, but is unique across all servers in a given replication
setup. There is a 1-to-1 mapping between all transactions and all
GTIDs.
--set-gtid-purged=OFF SET ##GLOBAL.gtid_purged is not added to the output, and SET
##SESSION.sql_log_bin=0 is not added to the output. For a server where
GTIDs are not in use, use this option or AUTO. Only use this option
for a server where GTIDs are in use if you are sure that the required
GTID set is already present in gtid_purged on the target server and
should not be changed, or if you plan to identify and add any missing
GTIDs manually.
Afterwards connect to your mysql with user root ,give permissions , flush them ,and verify that your user privileges were updated correctly.
mysql -u root -p
UPDATE mysql.user SET Super_Priv='Y' WHERE user='johnDoe' AND host='%';
FLUSH PRIVILEGES;
mysql> SHOW GRANTS FOR 'johnDoe';
+------------------------------------------------------------------+
| Grants for johnDoe |
+------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `johnDoe` |
| GRANT ALL PRIVILEGES ON `db1`.* TO `johnDoe` |
+------------------------------------------------------------------+
now reload the data and the operation should be permitted.
mysql -h [host] -u [user] -p[pass] [db_name] < [mysql_dump_name].sql
Full Solution
All the above solutions are fine. And here I'm gonna combine all the solutions so that it should work for all the situations.
Fixed DEFINER
For Linux and Mac
sed -i old 's/\DEFINER\=`[^`]*`#`[^`]*`//g' file.sql
For Windows
download atom or notepad++, open your dump sql file with atom or notepad++, press Ctrl+F
search the word DEFINER, and remove the line DEFINER=admin#% (or may be little different for you) from everywhere and save the file.
As for example
before removing that line: CREATE DEFINER=admin#% PROCEDURE MyProcedure
After removing that line: CREATE PROCEDURE MyProcedure
Remove the 3 lines
Remove all these 3 lines from the dump file. You can use sed command or open the file in Atom editor and search for each line and then remove the line.
Example: Open Dump2020.sql in Atom, Press ctrl+F, search SET ##SESSION.SQL_LOG_BIN= 0, remove that line.
SET ##SESSION.SQL_LOG_BIN= 0;
SET ##GLOBAL.GTID_PURGED=/*!80000 '+'*/ '';
SET ##SESSION.SQL_LOG_BIN = #MYSQLDUMP_TEMP_LOG_BIN;
There an issue with your generated file
You might face some issue if your generated dump.sql file is not proper. But here, I'm not gonna explain how to generate a dump file. But you can ask me (_)
Issue
Below statement or line your Dump file creating issue
DEFINER=username#`%
Simple Solution
The solution that you can workaround is to remove all the entries from SQL dump file and import data from the GCP console.
cat DUMP_FILE_NAME.sql | sed -e 's/DEFINER=`<username>`#`%`//g' > NEW-CLEANED-DUMP.sql
above command will help to remove all those lines from the dump file and create the new fresh dump file without Definer.
Try importing new file(NEW-CLEANED-DUMP.sql).
If you are on AWS RDS
You might see face issue, if your dump file is larger you can check the first 20 lines using
head -30 filename
once you can see output look for line and line number
SET ##SESSION.SQL_LOG_BIN= 0;
SET ##GLOBAL.GTID_PURGED=/*!80000 '+'*/ '';
SET ##SESSION.SQL_LOG_BIN = #MYSQLDUMP_TEMP_LOG_BIN;
we will remove these lines by line numbers for example 17,18,24 line number
sed -e '24d;17d;18d' file-name.sql > removed-line-file-name.sql
For importing database file in .sql.gz format, remove definer and import using below command
zcat path_to_db_to_import.sql.gz | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | mysql -u user -p new_db_name
Earlier, export database in .sql.gz format using below command.
mysqldump -u user -p old_db | gzip -9 > path_to_db_exported.sql.gz;
Import that exported database and removing definer using below command,
zcat path_to_db_exported.sql.gz | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | mysql -u user -p new_db
When you restore backup, Make sure to try with the same username for the old one and the new one.
I commented all the lines start with SET in the *.sql file and it worked.
If it helps, when I tried to restore a DB dump on my AWS MySQL RDS, I got this error:
ERROR 1227 (42000) at line 18: Access denied; you need (at least one of) the SUPER,
SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN privilege(s) for this operation
I didn't have to change the DEFINER or remove/comment out lines. I just did:
GRANT SESSION_VARIABLES_ADMIN ON *.* TO myuser#'myhost';
GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO myuser#'myhost';
And I was able to do the restore.
None of the above solutions worked for me. I had to do the following:
Use the following flags with mysqldump:
mysqldump --databases <db1> <db2> --master-data=1 --single-transaction --order-
by-primary --foce -r all.sql -h<host> -u<user> -p<password>
Remove the line that looks like:
CHANGE MASTER TO MASTER_LOG_FILE='binlog.....
In my file, that was line #22, so I ran: sed -i '22d' all.sql
Import the data to your RDS:
mysql -h<host> -u<user> -p<password>
$ source all.sql
In my case (trying to execute a SQL file into AWS RDS) the beginning of my SQL statement looked like this:
DROP VIEW IF EXISTS `something_view`;
CREATE ALGORITHM=UNDEFINED DEFINER=`root`#`%` SQL SECURITY DEFINER VIEW `something_view`...
All I had to do to fix it was to remove ALGORITHM=UNDEFINED DEFINER='root'#'%' SQL SECURITY DEFINER part of the above statement.
So the new statement looks like this:
CREATE VIEW 'something_view' ...
* Answer may only be applicable to MacOS *
When trying to import a .sql file into a docker container, I encountered the error message:
Access denied; you need (at least one of) the SUPER privilege(s) for
this operation
Then while trying some of the other suggestions, I received the below error on my MacOS (osx)
sed: RE error: illegal byte sequence
Finally, the following command from this resource resolved my "Access Denied" issue.
LC_ALL=C sed -i old 's/\DEFINER\=`[^`]*`#`[^`]*`//g' fileName.sql
So I could import into the docker database with:
docker exec -i dockerContainerName mysql -uuser -ppassword table < importFile.sql
Hope this helps! :)
Issue in dump.
Please try to get dump by following way:
mysqldump -h databasehost --user=databaseusername --password --single-transaction databasename | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | gzip > /tmp/database.sql.gz
Then, try to import by following way:
zcat /tmp/database.sql.gz | mysql -h database_host -u username -p databasename
Need to set "on" server parameter "log_bin_trust_function_creators" on server side. This one you can easily find on left side blade if it is azure maria db.

unable to set foreign key checks =0 from terminal

I am trying to run the following code from a linux (CentOS 7) terminal:
mysql -u root -p -e "SET FOREIGN_KEY_CHECKS = 0"; mysql -u root -p -Nse 'show tables' DATABASE_NAME -u root -p| while read table; do mysql -u root -p -e "truncate table $table" DATABASE_NAME; done;
But it apparently does not process the set foreign key checks command because in response I get:
ERROR 1701 (42000) at line 1: Cannot truncate a table referenced in a foreign key constraint (`atest`.`PARTICIPANT_2`, CONSTRAINT `FK_0a036647645f4e5e950470cb2dc` FOREIGN KEY (`PARTICIPANT_ACT_HJID`) REFERENCES `atest`.`ACT` (`HJID`))
Also, it continues to ask me for the password. I expect it to ask 3 times for the password, but not to repeat the three requests again and again. How can I change my code above to get it to run correctly, and with a minimal number of requests for password?
EDIT:
The following modification appears to be asking for the password for EVERY table in the loop. There are 500+ tables. How can I fix this so it only asks for the password a couple times?
mysql -u root -p -Nse 'show tables' DATABASE_NAME | while read table; do mysql -u root -p -e "SET FOREIGN_KEY_CHECKS = 0; truncate table $table" atest; done;
The foreign_key_checks is a session variable, it's in effect only for the current session, until it's changed, or until the session ends.
You are creating multiple database session, each new session starts with it's own foreign_key_checks variable, set to the default (inherited from the global setting). (I'm not going to mention how you change the default, because you do not really want to go there.)
One option would be to perform the SET FOREIGN_KEY_CHECKS statement in the same session as the TRUNCATE TABLE statement.
Use a semicolon as a statement separator. As a demonstration of running two statements:
mysql -u me -pXX -e "show variables like 'foreign%'; show variables like '%packet%';"

How to run SQL script in MySQL?

I want to execute a text file containing SQL queries, in MySQL.
I tried to run source /Desktop/test.sql and received the error:
mysql> . \home\sivakumar\Desktop\test.sql ERROR: Failed to open file
'\home\sivakumar\Desktop\test.sql', error: 2
Any idea on what I am doing wrong?
If you’re at the MySQL command line mysql> you have to declare the SQL file as source.
mysql> source \home\user\Desktop\test.sql;
You have quite a lot of options:
use the MySQL command line client: mysql -h hostname -u user database < path/to/test.sql
Install the MySQL GUI tools and open your SQL file, then execute it
Use phpmysql if the database is available via your webserver
you can execute mysql statements that have been written in a text file using the following command:
mysql -u yourusername -p yourpassword yourdatabase < text_file
if your database has not been created yet, log into your mysql first using:
mysql -u yourusername -p yourpassword
then:
mysql>CREATE DATABASE a_new_database_name
then:
mysql -u yourusername -p yourpassword a_new_database_name < text_file
that should do it!
More info here: http://dev.mysql.com/doc/refman/5.0/en/mysql-batch-commands.html
My favorite option to do that will be:
mysql --user="username" --database="databasename" --password="yourpassword" < "filepath"
I use it this way because when you string it with "" you avoiding wrong path and mistakes with spaces and - and probably more problems with chars that I did not encounter with.
With #elcuco comment I suggest using this command with [space] before so it tell bash to ignore saving it in history, this will work out of the box in most bash.
in case it still saving your command in history please view the following solutions:
Execute command without keeping it in history
extra security edit
Just in case you want to be extra safe you can use the following command and enter the password in the command line input:
mysql --user="username" --database="databasename" -p < "filepath"
All the top answers are good. But just in case someone wants to run the query from a text file on a remote server AND save results to a file (instead of showing on console), you can do this:
mysql -u yourusername -p yourpassword yourdatabase < query_file > results_file
Hope this helps someone.
I came here searching for this answer as well, and here is what I found works the best for me: Note I am using Ubuntu 16.x.x
Access mysql using:
mysql -u <your_user> - p
At the mysql prompt, enter:
source file_name.sql
Hope this helps.
Give the path of .sql file as:
source c:/dump/SQL/file_name.sql;
mysql> source C:\Users\admin\Desktop\fn_Split.sql
Do not specify single quotes.
If the above command is not working, copy the file to c: drive and try again.
as shown below,
mysql> source C:\fn_Split.sql
instead of redirection I would do the following
mysql -h <hostname> -u <username> --password=<password> -D <database> -e 'source <path-to-sql-file>'
This will execute the file path-to-sql-file
Never is a good practice to pass the password argument directly from the command line, it is saved in the ~/.bash_history file and can be accessible from other applications.
Use this instead:
mysql -u user --host host --port 9999 database_name < /scripts/script.sql -p
Enter password:
mysql -uusername -ppassword database-name < file.sql
So many ways to do it.
From Workbench: File > Run SQL Script -- then follow prompts
From Windows Command Line:
Option 1: mysql -u usr -p
mysql> source file_path.sql
Option 2: mysql -u usr -p '-e source file_path.sql'
Option 3: mysql -u usr -p < file_path.sql
Option 4: put multiple 'source' statements inside of file_path.sql (I do this to drop and recreate schemas/databases which requires multiple files to be run)
mysql -u usr -p < file_path.sql
If you get errors from the command line, make sure you have previously run
cd {!!>>mysqld.exe home directory here<<!!}
mysqld.exe --initialize
This must be run from within the mysqld.exe directory, hence the CD.
Hope this is helpful and not just redundant.
From linux 14.04 to MySql 5.7, using cat command piped with mysql login:
cat /Desktop/test.sql | sudo mysql -uroot -p
You can use this method for many MySQL commands to execute directly from Shell. Eg:
echo "USE my_db; SHOW tables;" | sudo mysql -uroot -p
Make sure you separate your commands with semicolon (';').
I didn't see this approach in the answers above and thought it is a good contribution.
Very likely, you just need to change the slash/blackslash:
from
\home\sivakumar\Desktop\test.sql
to
/home/sivakumar/Desktop/test.sql
So the command would be:
source /home/sivakumar/Desktop/test.sql
use the following from mysql command prompt-
source \\home\\user\\Desktop\\test.sql;
Use no quotation. Even if the path contains space(' ') use no quotation at all.
Since mysql -u yourusername -p yourpassword yourdatabase < text_file did not work on a remote server (Amazon's EC2)...
Make sure that the Database is created first.
Then:
mysql --host=localhost --user=your_username --password=your_password your_database_name < pathTofilename.sql
For future reference, I've found this to work vs the aforementioned methods, under Windows in your msql console:
mysql>>source c://path_to_file//path_to_file//file_name.sql;
If your root drive isn't called "c" then just interchange with what your drive is called. First try backslashes, if they dont work, try the forward slash. If they also don't work, ensure you have your full file path, the .sql extension on the file name, and if your version insists on semi-colons, ensure it's there and try again.
If you are here LOOKING FOR A DRUPAL ENVIRONMENT
You can run with drush command on your project directory
drush sqlc
If you are trying this command :
mysql -u root -proot -D database < /path/to/script.sql
You may get an error like this : if you have special characters, mainly '`'
ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '/path/to/script.sql' at line 1
So I would suggest to use a command like this :
echo "source /path/to/script.sql" | mysql -u root -proot -D database
This command will execute source /path/to/script.sql once connected to the server, which execute your script.
I had this error, and tried all the advice i could get to no avail.
Finally, the problem was that my folder had a space in the folder name which appearing as a forward-slash in the folder path, once i found and removed it, it worked fine.
I use Bash's Here Strings for an instant SQL execution:
mysql -uroot -p <<<"select date(now())"
https://www.gnu.org/software/bash/manual/html_node/Redirections.html#Here-Strings