MySQL Bash script with variables - mysql

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.

Related

execute MYSQL commands from a file in terminal

I've been searching to understanding the following MySQL command:
framework_mariadb.sql | mysql -u username -p password -h 127.0.0.1 -P 26257 target
My guess was the sql statements within the sql file get executed by mysql for the given target/database. But then I came across the source command in MySQL, ie
\bin\mysql -u root -p testdatabase < C:\Users\Juan\Desktop\databasebackup.sql
So my question is, does the first command and the second command essentially do the same thing? My apologies if this has already been asked, I haven't been able to find details for the first SQL command.
This is more about Linux shell capabilities than it is about MySQL.
The second form runs the mysql client, and uses the < symbol to tell it to take its input from the specified file.
The first form does essentially the same thing, but uses the pipe character | to indicate that the output of the first command should be sent to the input of the second command.
However, for the first form I'd expect the line to start with cat (as in cat framework_mariadb.sql | mysql ...) because the SQL script won't normally run as a shell command. cat is a command that reads one or more files and send s them to its output.
It is possible to set the SQL script up to run like this, but that requires a specific line (#! /bin/cat or similar) to be present at the top of the file, and the file must have the execution bit set. (At least, that's how I'd do it. There might be some other bash magic I'm not aware of. bash is not my forté)
There are many resources on the web that can teach the fundamentals of the Linux shell. You could try Microsoft's Introduction to bash, but there are many others.

Escaping special characters in mysql password while executing mysql query on remote host

I'm trying to run a mysql query on a remote host using a bash script.
${MYSQL} -u ${USER} -p${PASS} -P${PORT} -h ${HOST} -e "select * from information_schema;"
My PASS looks something like "dfsf#DFD". It conatins '#' character.
For some reasons the PASS is not retrieving correctly in the script. Its getting chopped off after '#'.
And for some reason including source /etc/environment in the script, seems to fix the problem.
I want to understand why is this happening. How to make it work without the source statement.
As far as I know - the safest way to specify remote connection details for MySQL is using configuration file: https://dev.mysql.com/doc/refman/8.0/en/option-files.html
So briefly you just put something like this in ~/.my.cnf file:
[client]
host='...'
port='...'
user='...'
password='...'
And then you simply run
mysql -e "select * from information_schema;"
Not sure it suits your situation, but it should solve your issue, if you quote the values.
Quoting at command line is also a solution, but your credentials will be visible to everyone able to see your processes at the system where you run that.

Copy value from one database to another using MySQL CLI

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.

BASH script get's row data from mySQL and uses that to launch PHP scrips

I've been trying for a few hours now to store row data into a BASH var then use that to launch some PHP scripts.
So far, I've only been able to echo out the whole result set. I have since broken that script, so I can't even paste it here. This is what I have, that's not working at all.
#! bin/bash
query=`echo "SELECT id FROM searches WHERE running=1 AND id_user=2" | mysql -u root`
I've never used BASH before, so I'm completely lost.
What I'm asking for is some resources that can show me how I can connect to mysql, then loop through a result set using the data from that row.
Thanks.
You can read mysql --silent output into Bash vars with while read:
>sql="SELECT id FROM searches WHERE running=1 AND id_user=2"
>mysql --silent -u ctrahey test -e "$sql" |while read myid; do
php -f my_processor.php $myid;
done
>
Notes:
sql="... sets a Bash variable of your sql (not actually necessary, just aides readability)
mysql -e the -e option allows you to pass in a query, so you don't need STDIN
mysql --silent --silent suppresses the extra formatting mysql usually does. in my testing, this was actually also unnecessary (the pipe chars in the output did not mess up Bash)
php -f .. this executes a php file, passing the current id as an arg.
Bash is not a good language for interacting with mysql, it only works for very very simple cases. Use php instead (since you mentioned php), it has an api for interacting with mysql databases sanely. And yes, you can run a php script as you would a bash script.
If you want to run a single command with MySQL, use mysql -e or mysql --execute. They are the same command, but the second version is more memorable. If you add this flag to the above, the rows will be stored in the variable.
However, as mentioned by geirha, BASH may not be the best language to get row data. But if you choose to parse it wish BASH, mysql -e is the right command to execute queries.

replacing sqlplus commands with mysql commands

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