I have two databases fooDB and barDB, both having a structurally identical table named options. I want to copy the value of one cell in fooDB.options to barDB.options. I can't use (non local) outfiles and I have two users, both having only access to one of the two databases. Copy and paste with the mouse does not work, as the value is too complex.
Any ideas, how to copy the value with the MySQL command line client? I thought of using variables, but AFAIK you can't change your user in the same CLI session. Any ideas? It should be a simple and fast solution: Of course I can do a mysqldump or whatever, but this is overkill for just one value (and takes too much time).
The idea is to generate SQL script which updates (or inserts) required value. To generate SQL use this command (username1 - username for fooDB database):
mysql -u username1 -p -N -s -r -e "SELECT CONCAT('UPDATE barDB.options SET value = ', QUOTE(value), ' WHERE id = 1;') FROM fooDB.options WHERE id = 1" > file_name.sql
Then you get file_name.sql with something like:
UPDATE barDB.options SET value = 'Your value here' WHERE id = 1;
Then just run this script (username2 - username for barDB database):
mysql -u username2 -p < file_name.sql
Some used MySQL command line options:
-N - do not write column names in results
-s - use nontabular output format
-r - disable character escaping
I disable character escaping in command line options, because special characters are already escaped with QUOTE function in SELECT query.
Related
How can I execute multiple SQL queries in the bash script?
I read these two posts from previous years:
A better way to execute multiple MySQL commands using shell script
How to execute a MySQL command from a shell script?
They brought some clarification, but there is still something I do not understand.
I have multiple queries for deleting information about subject with defined subject_id.
Unfortunately I need to run all of them since the table is not in the "cascade" mode.
Is there a way, to create a bash script in which I can use the "user given" variable (by that I mean for example [ read -p 'Subject ID' SUBJECT_ID ]) that will be used inside as the subject_id in each of the queries?
Do I still have to adjust everything to this:
mysql -h "server-name" -u root "password" "database-name" < "filename.sql"
or is there a way to just run this script with connection to db from .cnf file inside it?
There are two questions above. One is how to get a bash variable into your SQL script. I would do this:
read -p 'Subject ID' SUBJECT_ID
mysql -e "SET #subject = '${SUBJECT_ID}'; source filename.sql;"
Bash will expand ${SUBJECT_ID} into the string before it uses it as an argument to the mysql -e command. So the MySQL variable is assigned the string value of SUBJECT_ID.
This will be tricky if SUBJECT_ID may contain literal single-quote characters! So I suggest using Bash syntax for string replacement to make each single-quote in that into two single-quotes:
mysql -e "SET #subject = '${SUBJECT_ID//'/''}'; source filename.sql;"
Note you must put a semicolon at the end after the filename.
The second question is about specifying the host, user, and password. I would recommend putting these into an options file:
[client]
host=server-name
user=root
password=xyzzy
Then when you invoke the mysql client:
mysql --defaults-extra-file myoptions.cnf -e '...'
This is a good idea to avoid putting your plaintext password on the command-line.
Read https://dev.mysql.com/doc/refman/8.0/en/option-files.html for more details on option files.
I want to do something like this:
cat files_list | cut -d' ' -f1,3 | mysql -uroot -pxxxx -e "insert into table(var1, var2) values($f1,$f2)"
How can i achieve this thing?
You can use the following bash script:
while read -a record ; do
mysql -uroot -pxxxx -e "insert into table(var1, var2) values(${record[0]}, ${record[2]})"
done < files_list
However, this is simple but performs not very well.
If the task is performance critical, I would build just a single mysql query, which inserts all rows at once, or even better: use LOAD_DATA_INFILE
Also note, if the task is security critical, meaning the input data comes from an untrusted source, I wouldn't use the command line mysql client at all. Using a programming language which supports prepared statements for mysql - like PHP - would be the way to go.
Using a programming language would had another important advantage - you wouldn't need to pass the password via commandline which is insecure.
i am trying to rewrite a script that is written in c-shell script to that uses sql plus command to get information from an oracle database but i am replacing it with mysql and i would like to replace all sqlplus syntax with mysql syntax. I am asking all the c-shell gurus to explain to me what this command means
set SQLPLUS=${ORACLE_HOME}/bin/sqlplus
set REPORT=${MYBD_HOME}/Scripts/report.sql
so somewhere along the line i invoke the sql plus command using the follwing
${SQLPLUS} ${MYDBUSER} # &{REPORT}
i am able to say i undertand what the right hand values mean ({ORACLE_HOME}/bin/sqlplus) is the path to where my sqplus command is located and thus i need it to invoke the command and the {REPORT=$(MYBD_HOME}/Scripts.report.sql) is the path where my sql script that is to be ran by invoking the sqplus command resides correct?
what i dont understand is what the set command is initializing this to. is SQLPLUS a variable so i dont have to type the path when i try to put it in my .csh script?
If so then all i need to do to run this script on a mysql database is simply set the SQLPLUS(problably change it to MYSQL) to point to the path where my msql exec is right
set MYSQL=${MYSQL_HOME}/bin/mysql
then just invoke mysql and run the sql statement
${MYSQL}${MYDBUSER}#${REPORT}
is this what i need to do ro tun the same .tsch script to get data from a mysql table?
You'll need something like this:
${MYSQL} -u $username -p$password -D $database < ${REPORT}
(The username and password are passed in differently to the mysql executable than they are passed to SQLPlus. You'll need to parse out the username and the password from ${MYDBUSER}. Likely, that contains a string such as "scott/tiger". The equivalent on the mysql command line client would be "-u scott -ptiger -D scott".
That # (at sign) is a SQLPlus thing; it tells SQLPLus to read input from the specified filename. The equivalent in mysql would be the source command, e.g.
${MYSQL} -u $username -p$password <_EOD!
use $database
source ${REPORT}
_EOD!
Also, your report.sql file likely includes spool and other SQLPLus specific commands. The mysql command line client is NOT ANYWHERE near as powerful a reporting tool as SQLPlus is.
Addendum:
Q: what exactly does the spool do?
The SQLPlus spool command directs output to a file. It's frequently used to create a log file from a SQLPLus session, and is also useful for creating report files.
set trimspool on
spool /tmp/file.lis
select 'foo' as foo from dual;
spool off
Q: Why can't i set the user name and passowrd to a variable and use that?
You could set a variable, the end result of the command line sent to the OS would be the same.
set MYDBUSER="-u username -ppassword -D database"
${MYSQL} ${MYDBUSER} <${REPORT}
Q:Seems like mysql is more verbose than sqlplus.
The mysql command line client takes unix-style options. These are equivalent:
mysql -u myusername -pmypassword -D mydatabase
mysql --user=myusername --password=mypassword --database=mydatabase
I have a mysql database with a blob field containing a zip and I need to save it as a file on disk, from bash. I'm doing the following but the end result doesn't read as a zip... Am I doing something wrong or is the file stored not actually a zip (the entry in the database is actually created by a seismological station, so I have no control over it)?
echo "USE database; SELECT blobcolumn FROM table LIMIT 1" | mysql -u root > file.zip
then I open file.zip with a file editor and remove first line which contains the column header. Then 'unzip' doesn't recognize it as a zip file.
For a gzipped blob you can use:
echo "use db; select blob from table where id=blah" | mysql -N --raw -uuser -ppass > mysql.gz
I have not tried this with a zip file.
The proper way to do this would be to use DUMPFILE, otherwise mysql will mess up your data.
mysql -uroot -e "SELECT blobcolumn INTO DUMPFILE '/tmp/file.zip' FROM table LIMIT 1" database
I know this is an old question, but I needed the answer myself, so this is what worked for me.
I found that mysql appends a newline character at the end, which needs to be removed before the correct binary value remains.
echo "USE database; SELECT blobcolumn FROM table LIMIT 1" | mysql -N --raw -u root | head -c -1 > file.zip
you would need to skip column, like
sql="USE database; SELECT blobcolumn FROM table LIMIT 1"
mysql -u root -N <<< $sql > file.zip
I have many databases with different names.
I want to drop multiple databases, Is there any command since all names of db are different.
Eg: mysql db, Test db, live db.
As of I know, there is no specific command/query to delete multiple databases without having a specific pattern in their names. Even I was asked to do the favor several times. So I researched and found no specific solution. Then I tried the below hack. It worked without giving much trouble. May be it could help for you too.
Take all the databases using the below command.
SHOW DATABASES ;
Paste all of them in an excel/some other text file (I prefer NPP). Keep the only names which you want to delete from the list. Dont forget to remove your working db's from the list.
Add DROP DATABASE in front of those names.
That's it simple. Copy & Paste all of those in your workbench. You can execute all of them in one shot.
If you create a shell script this should remove all the databases. You will need to edit it to suit your needs.
DBUSER='user'
DBPASS='password'
SQLFILE='/path/to/file/databases.sql'
echo '* Dropping ALL databases'
DBS="$(mysql -u$DBUSER -p$DBPASS -Bse 'show databases' | grep -v Database | grep -v database | grep -v mysql | grep -v information_schema)"
for db in $DBS; do
echo "Deleting $db"
mysql -u$DBUSER -p$DBPASS -Bse "drop database $db; select sleep(0.1);"
done
First run this query to produce a list of drop commands:
select CONCAT('drop database `', schema_name,'`;') as database_name from information_schema.schemata where schema_name like '%DATABASES_TO_REMOVE%' order by schema_name;
Then copy the output rows of this query and paste into a query window
In my case I then needed to remove the single-quotes (') surrounding the resulting command queries which I did using a simple find + replace (often Ctrl + H, replace ' with < empty >)
And execute (highlighting all of the drop statements in my case)!
Unfortunetly, there is nothing like that, unless you create your own function.
simple bash script can be done this work
#!/bin/bash
cat /home/mshafee/file | while read line
do
mysql -u username -p****** -h 0.0.0.0 -e "drop database $line;"
done
here provide username, password and IP address.