How to convert MySQL query output in array in shell scripting? - mysql

I am storing output of MySQL query in a varible using shell scripting. The output of SQL query is in multiple rows. When I checked the count of the variable (which I think is an array), it is giving 1. My code snippet is as follows:
sessionLogin=`mysql -ugtsdbadmin -pgtsdbadmin -h$MYSQL_HOST -P$MYSQLPORT CMDB -e " select distinct SessionID div 100000 as 'MemberID' from SessionLogin where ClientIPAddr like '10.104%' and LoginTimestamp > 1426291200000000000 order by 1;"`
echo "${#sessionLogin[#]}"
How can I store the MySQL query output in an array in shell scripting?

You can loop over the output from mysql and append to an existing array. For example, in Bash 3.1+, a while loop with process substitution is one way to do it (please replace the mysql parameters with your actual command)
output=()
while read -r output_line; do
output+=("$output_line")
done < <(mysql -u user -ppass -hhost DB -e "query")
echo "There are ${#output[#]} lines returned"
Also take a look at the always excellent BashFaq

Related

Mysql query to update multiple rows using a input file from linux

I'm trying to update multiple rows in a DB using a small script.
I need to update the rows based on some specific user_ids which I have in a list on Linux machine.
#! /bin/bash
mysql -u user-ppassword db -e "update device set in_use=0 where user_id in ()";
As you see above, the user_ids are in a file, let's say /opt/test/user_ids_txt.
How can I import them into this command?
This really depends on the format of user_ids_txt. If we assume it just happens to be in the correct syntax for your SQL in statement, the following will work:
#! /bin/bash
mysql -u user-ppassword db -e "update device set in_use=0 where user_id in ($(< /opt/test/user_ids_txt))";
The bash interpreter will substitute in the contents of the file. This can be dangerous for SQL queries, so I would echo out the command on the terminal to make sure it is correct before implementing it. You should be able to preview your SQL query by simply running the following on the command line:
echo "update device set in_use=0 where user_id in ($(< /opt/test/user_ids_txt))"
If your file is not in the SQL in syntax you will need to edit it (or a copy of it) before running your query. I would recommend something like sed for this.
Example
Let's say your file /opt/test/user_ids_txt is just a list of user_ids in the format:
aaa
bbb
ccc
You can use sed to edit this into the correct SQL syntax:
sed 's/^/\'/g; s/$/\'/g; 2,$s/^/,/g' /opt/test/user_ids_txt
The output of this command will be:
'aaa'
,'bbb'
,'ccc'
If you look at this sed command, you will see 3 separate commands separated by semicolons. The individual commands translate to:
1: Add ' to the beginning of every line
2: Add ' to the end of every line
3: Add , to the beginning of every line but the first
Note: If your ID's are strictly numeric, you only need the third command.
This would make your SQL query translate to:
update device set in_use=0 where user_id in ('aaa'
,'bbb'
,'ccc')
Rather than make a temporary file to store this, I would use a bash variable, and simply plug that into the query like this:
#! /bin/bash
in_statement="$(sed 's/^/\'/g; s/$/\'/g; 2,$s/^/,/g' /opt/test/user_ids_txt)"
mysql -u user-ppassword db -e "update device set in_use=0 where user_id in (${in_statement})";

BASH MYSQL FETCH FIELDS

i have this code:
for file in $(ls -I *.bad1 -I *.bad2 $1); do
query="select file_name,dest_path,new_file_name from FILES where
file_name='"${file%%\_*}"'"
while read -a row
do
name="${row[0]}"
dest="${row[1]}"
new_name="${row[2]}"
echo $name
echo $dest
echo $new_name
done < <(echo $query | mysql -N -u root -pcorollario86 -D test)
done
It work but the select statement i need is:
select max(file_name),max(dest_path),max(new_file_name) from FILES where
file_name='"${file%%\_*}
because i have to compare the return value of each field from the statement (>0 or =0).
The problem is that when i use this second statement BASH give me an error
regard the use of aggregation function.
I DON'T NEED TO PRINT EACH FIELDS. I NEED TO FETCH EACH FIELD INTO A VARIABLE.
Exists another way to fetch every single field from select statement into single variable?
Any suggestion please?
Thanks in advance.

Detect and delete line break directly out of mysql query

im trying to detect and delete a line break out of a subject (called m.subject) mail information retrieved via CONCAT out of a mysql database.
That said, the linebreak may or may not occur in the subject and therefore must be detected.
My query looks like this:
mysql --default-character-set=utf8 -h $DB_HOST -D $TARGET -u $DB_USER -p$DB_PW -N -r -e "SELECT CONCAT(m.one,';',m.two,';',m.three,';',m.subject,';',m.four';',m.five,';',(SELECT CONCAT(special_one) FROM special_$SQL_TABLE WHERE msg_id = m.six ORDER BY time DESC LIMIT 1)) FROM mails_$SQL_TABLE m WHERE m.rtime BETWEEN $START AND $END AND m.seven = 1 AND m.eight IN (2);"
I tried to delete it afterwards, but getting in performance trouble due to several while operations on all lines already. Is there an easy way to detect and cut it directly via the CONCAT buildup? It is crucial to retrieve only one line after extraction for me.
Updating/changing the database is not an option for me, as I only want to read the current state.

Can't select some mysql data and store it to a variable in bash

All of the other variables that make this work are tested and working correctly so I'm obviously doing this wrong.
I have a bash script that first selects some mysql data and stores into a new variable.
Then it goes on to connect again and update the database.
title=$(mysql -u $user -p$pass -h $host dbname | SELECT post_title FROM wp_posts WHERE ID=$8);
mysql --host=$host --user=$user --password=$pass dbname <<EOF
UPDATE wp_my_music_lib SET title = "$title" WHERE track_id=${4}${6};
EOF
The title entry is always blank which says to me that the initial SELECT isn't working properly. It should also be noted that the data expected from the select result has white space and special chars in it ie :
Some Artist (10/10/13)
I thought quoting the var "$title" would fix any potential problems with gobbling but that isn't the issue here as I've tried selecting a single numerical object from a different column and that doesn't work either.
If I hard code the title var it works as expected.
1) Can you see what I'm doing wrong?
2) Is it possible to perform all of the above with one db connection instead as that would make more sense?
mysql | SELECT pipes the output of mysql to a command called SELECT, which is сertainly not what you want.
To execute a query via mysql and capture the output you can use this syntax:
title=$(mysql -B dbname <<< "SELECT post_title FROM wp_posts WHERE ID=$8")
You could also execute the SELECT in a subquery to avoid multiple calls to mysql:
mysql --host=$host --user=$user --password=$pass dbname <<EOF
UPDATE wp_my_music_lib SET title = (
SELECT post_title FROM wp_posts WHERE ID=$8)
WHERE track_id=${4}${6}
EOF

Heredocs, variables and single quotes in BASH and MySQL

I'm trying to send some data to a remote MySQL database using a BASH script on GNU/Linux, but get various errors.. Here's the line that's not working:
mysql --host=192.168.0.100 --user=petercapaldi --password=mypassword mystartrekcharacterbase << EOF
INSERT into myfourlegs values ('$PERSON','$THETIME','$THETIME','$THEDATE','$DAYOFWEEK');
EOF
and this too (just in case):
mysql --host=192.168.0.100 --user=petercapaldi --password=mypassword mystartrekcharacterbase << EOF
INSERT into myfourlegs values (\047$PERSON\047,\047$THETIME\047,\047$THETIME\047,\047$THEDATE\047,\047$DAYOFWEEK\047);
EOF
Scrap that. My fault - missed the first field in the database. The single quotes work as they should with heredocs.. (i.e. '$VARIABLE' prints 'myvariable' just like $VARIABLE prints myvariable).