Bash script: Mysql query field to variable - mysql

I'm trying to obtain a recordset and read a few fields from it. I'm not able to figure it out how put the fields into variables. The script is:
#!/bin/bash
sqlQuery="$(mysql -h host -u user -ppass -D oberonsaas_v2 -s -N -e
'select ventas.id_venta,
ventas_entradas.id_ventas_entradas,
ventas.id_evento,
id_tarifa,
DATE_FORMAT(fecha_evento,"%Y%m%d") as fecha,
TIME_FORMAT(pase,"%H%i") as pase
from pases,ventas,ventas_entradas,recintos
where ventas.id_recinto = recintos.id_recinto
and ventas.id_pase = pases.id_pase
and ventas.id_venta = ventas_entradas.id_venta
and recintos.id_cliente = 32
and ventas.estado="Pagada"
and date(fecha_venta) = date_add(date(CURRENT_TIMESTAMP),INTERVAL -1 day)')"
echo $sqlQuery
I get all the recordset in $sqlQuery, but i want to do a loop and concat the fields.

Well I have invented some output
#!/bin/bash
Result="21,336,purchase,tarif_exspensive,Jose"
(IFS=","
for i in $Result
do
echo "I Have: " $i
done
)
Ouput is
$ bash t5.sh
I Have: 21
I Have: 336
I Have: purchase
I Have: tarif_exspensive
I Have: Jose

Collapse this into the simplest possible construct.
Put returned recordset into a bash array (for example):
sqlQuery=( pases_value ventas_value ventas_entradas_value recintos_value )
note: yours could look like:
sqlQuery=( $(mysql -h host ... )
new lines between the array operators "(" and ")" are ok
each will be in a distinct sqlQuery array location.
for example return: recintos_value
echo ${sqlQuery[3]}
concat all:
echo ${sqlQuery[*]}
if delimiters are of concern, use the mysql --delimiter switch to define a desired character, then
set concatValue=${sqlQuery[*]}
then to remove the delimiter character ("," for example):
set finalValue=${concatValue//,}

Related

RESOLVED - How can I replace start and end of line and concat line with sed

I want to store the result of my SQL query in a variable in order to use it in another query in the "in" clause.
When I do it with an INT list I have found the solution but in the context of a varach I have not yet found it.
Do you have an idea?
For information, for the int I use:
listID=$(/usr/mysql-5.5.40/bin/mysql -u$USER -p$PASSWORD -h$HOST -P$PORT $SCHEMA -e "SELECT ID FROM MYTABLE where NAME="toto";"|sed '1d;:a;N;$!ba;s/\n/,/g' )
In this case I can use listID for
NBMESSAGE=$(/usr/mysql-5.5.40/bin/mysql -u$USER -p$PASSWORD -h$HOST -P$PORT $SCHEMAMESSAGE -e "SELECT count(*) FROM MESSAGE where AUTOR_ID in ($listID)"|sed '1d')
then, I do
echo " Nombre de message $NBMESSAGE "
Thanks
Edit:
I had test my requete and result is good and produce this , in the Database ID are VARCHAR:
ID
1
12
13
14
15
16
17
When I pass |sed '1d;:a;N;$!ba;s/\n/,/g' I obtain
1,12,13,14,15,16,17
But I want have:
'1','12','13','14','15','16','17'
When I manage to get this result I will pass it in another query which does a count. I would post it as well.
EDIT 2:
I Solve my problem with this command, I share it with you :
listID=$(/usr/mysql-5.5.40/bin/mysql -u$USER -p$PASSWORD -h$HOST -P$PORT $SCHEMA -e "SELECT ID FROM MYTABLE where NAME="toto";"|se
d '1d;:a;N;$!ba;s/\n/'"'"','"'"'/g;s/^/'"'"'/g;s/$/'"'"'/g')
In this cas when I do a
echo " $listID "
I obtain '1','2','3','4'
thanks
Since I do not have a MySQL database with your dataset, I built this simple script that prints the output you are expecting:
printoutput.bash
#!/bin/bash
#
echo "ID"
echo "1"
echo "12"
echo "13"
echo "14"
echo "15"
echo "16"
echo "17"
This second script processes the output from the script above:
#!/bin/bash
# Read the result of the command into an array
# If the command fails, \0 is returned. The RESULTS array will have only 1 empty element
IFS=$'\n' read -r -d '' -a RESULTS < <(./printoutput.bash && printf '\0')
# Remove the first element
unset 'RESULTS[0]'
# Just to check that the unset worked
declare -p RESULTS
echo "-----------------------------------------------------------"
# This loops through the array, adding ' before and ', after each value
result=$(printf "'%s'," "${RESULTS[#]}")
# Remove the last ,
finalresult="${result%?}"
echo "$finalresult"
The method I use is to get rid of the \n all together by sending the output to an array. The array is then printed, adding single quotes and a comma. Then the last comma is removed.
Running the second script gives me the output you wanted:
./secondscript.bash
declare -a RESULTS=([1]="1" [2]="12" [3]="13" [4]="14" [5]="15" [6]="16" [7]="17")
-----------------------------------------------------------
'1','12','13','14','15','16','17'

Bash script with variable from a different file in array

I have a config.txt file with the following:
VAR=('a' 'b' 'c')
database='mydb'
and I want to use the VAR variable in the script (myscript.sh) to check if any of the data in it exists in a search that will be made on the database.
The search I am doing is like this:
output=$(mysql $database -u $user -p$pass -se "select name from my_table where word = '$VAR'")
You can read files into your script with the source command (aliased simply as .) like so:
. config.txt
# or
source config.txt
To get a comma separated string, check for example here
To expand on #Olli's answer:
source config.txt
# SQL injection
# values=$(printf "'%s'\n" "${VAR[#]}" | paste -sd,)
values=$(printf "'%s'\n" "${VAR[#]//\'/\'\'}" | paste -sd,)
select="select name from my_table where word in ($values)"
output=$(mysql "$database" -u "$user" -p"$pass" -se "$select")

How to embed BASH variable in MySQL query in shell script file

#!/bin/bash
fut=$(date -d "+14 days" +'%Y-%m-%d')
echo $fut
mysql -u user -ppassword base1 << "EOF"
INSERT INTO tableB SELECT * FROM tableA WHERE startdate < $fut;
....many lines of MySQL....
EOF
Mysql engine doesn't understand $fut as a variable. What syntax should be applied to make this work?
I have no problem with using a here-document, but I would like to suggest another possibility which is slightly more verbose, but has advantages when you may have to do more than just substituting variables : piping the output of a function.
#!/bin/bash
sql_statement()
{
local fut=$(date -d "+14 days" +'%Y-%m-%d')
echo "INSERT INTO tableB SELECT * FROM tableA WHERE startdate < $fut;"
echo "....many lines of MySQL...."
}
mysql -u user -ppassword base1 < <(sql_statement)
This is not required in this specific case, but allows the function to have additional logic (e.g. if blocks, loops...) to generate a more complex or variable SQL statement. As a general solution, it has nice advantages.
You need to remove the " from the EOF:
#!/bin/bash
fut=$(date -d "+14 days" +'%Y-%m-%d')
echo $fut
mysql -u user -ppassword base1 << EOF
INSERT INTO tableB SELECT * FROM tableA WHERE startdate < $fut;
....many lines of MySQL....
EOF
From bash docs:
No parameter substitution when the "limit string" is quoted or escaped.

BASH: Assigning MySQL SELECT result elements to different variables

Perhaps I am overcomplicating but ,I'm have built the following statement:
query="SELECT url, users FROM result as r INNER JOIN search as s ON s.UID = r.SearchID WHERE s.isProcessed = 0
The next step is to loop though the result but I need to be able to call urls and users separately. That's how I am attempting it:
while read -r link users; do
output+=("$link", "$users")
done < <(mysql -h $host -u $user -p$pwd -s -N -D $db -e "$query")
for i in ${!output[#]} ; do
echo "${output[i]}"
Any hint how to echo users only, please?
The above will return both urls and users :(
The users are in the odd-numbered elements of $output, so start at 1 and increment the array index by 2.
for ((i=1; i < ${#output[#]}; i+=2)); do
echo "${output[$i]}"
done

Store mysql result in a bash array variable

I am trying to store MySQL result into a global bash array variable but I don't know how to do it.
Should I save the MySQL command result in a file and read the file line by line in my for loop for my other treatment?
Example:
user password
Pierre aaa
Paul bbb
Command:
$results = $( mysql –uroot –ppwd –se « SELECT * from users );
I want that results contains the two rows.
Mapfile for containing whole table into one bash variable
You could try this:
mapfile result < <(mysql –uroot –ppwd –se "SELECT * from users;")
Than
echo ${result[0]%$'\t'*}
echo ${result[0]#*$'\t'}
or
for row in "${result[#]}";do
echo Name: ${row%$'\t'*} pass: ${row#*$'\t'}
done
Nota This will work fine while there is only 2 fields by row. More is possible but become tricky
Read for reading table row by row
while IFS=$'\t' read name pass ;do
echo name:$name pass:$pass
done < <(mysql -uroot –ppwd –se "SELECT * from users;")
Read and loop to hold whole table into many variables:
i=0
while IFS=$'\t' read name[i] pass[i++];do
:;done < <(mysql -uroot –ppwd –se "SELECT * from users;")
echo ${name[0]} ${pass[0]}
echo ${name[1]} ${pass[1]}
New (feb 2018) shell connector
There is a little tool (on github) or on my own site: (shellConnector.sh you could use:
Some preparation:
cd /tmp/
wget -q http://f-hauri.ch/vrac/shell_connector.sh
. shell_connector.sh
newSqlConnector /usr/bin/mysql '–uroot –ppwd'
Following is just for demo, skip until test for quick run
Thats all. Now, creating temporary table for demo:
echo $SQLIN
3
cat >&3 <<eof
CREATE TEMPORARY TABLE users (
id bigint(20) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(30), date DATE)
eof
myMysql myarray ';'
declare -p myarray
bash: declare: myarray: not found
The command myMysql myarray ';' will send ; then execute inline command,
but as mysql wont anwer anything, variable $myarray wont exist.
cat >&3 <<eof
INSERT INTO users VALUES (1,'alice','2015-06-09 22:15:01'),
(2,'bob','2016-08-10 04:13:21'),(3,'charlie','2017-10-21 16:12:11')
eof
myMysql myarray ';'
declare -p myarray
bash: declare: myarray: not found
Operational Test:
Ok, then now:
myMysql myarray "SELECT * from users;"
printf "%s\n" "${myarray[#]}"
1 alice 2015-06-09
2 bob 2016-08-10
3 charlie 2017-10-21
declare -p myarray
declare -a myarray=([0]=$'1\talice\t2015-06-09' [1]=$'2\tbob\t2016-08-10' [2]=$'3\tcharlie\t2017-10-21')
This tool are in early step of built... You have to manually clear your variable before re-using them:
unset myarray
myMysql myarray "SELECT name from users where id=2;"
echo $myarray
bob
declare -p myarray
declare -a myarray=([0]="bob")
If you're looking to get a global variable inside your script you can simply assign a value to a varname:
VARNAME=('var' 'name') # no space between the variable name and value
Doing this you'll be able to access VARNAME's value anywhere in your script after you initialize it.
If you want your variable to be shared between multiple scripts you have to use export:
script1.sh:
export VARNAME=('var' 'name')
echo ${VARNAME[0]} # will echo 'var'
script2.sh
echo ${VARNAME[1]} # will echo 'name', provided that
# script1.sh was executed prior to this one
NOTE that export will work only when running scripts in the same shell instance. If you want it to work cross-instance you would have to put the export variable code somewhere in .bashrc or .bash_profile
The answer from #F. Hauri seems really complicated.
https://stackoverflow.com/a/38052768/470749 helped me realize that I needed to use parentheses () wrapped around the query result to treat is as an array.
#You can ignore this function since you'll do something different.
function showTbl {
echo $1;
}
MOST_TABLES=$(ssh -vvv -t -i ~/.ssh/myKey ${SERVER_USER_AND_IP} "cd /app/ && docker exec laradock_mysql_1 mysql -u ${DB} -p${REMOTE_PW} -e 'SELECT table_name FROM information_schema.tables WHERE table_schema = \"${DB}\" AND table_name NOT LIKE \"pma_%\" AND table_name NOT IN (\"mail_webhooks\");'")
#Do some string replacement to get rid of the query result header and warning. https://stackoverflow.com/questions/13210880/replace-one-substring-for-another-string-in-shell-script
warningToIgnore="mysql\: \[Warning\] Using a password on the command line interface can be insecure\."
MOST_TABLES=${MOST_TABLES/$warningToIgnore/""}
headerToIgnore="table_name"
MOST_TABLES=${MOST_TABLES/$headerToIgnore/""}
#HERE WAS THE LINE THAT I NEEDED TO ADD! Convert the string to array:
MOST_TABLES=($MOST_TABLES)
for i in ${MOST_TABLES[#]}; do
if [[ $i = *[![:space:]]* ]]
then
#Remove whitespace from value https://stackoverflow.com/a/3232433/470749
i="$(echo -e "${i}" | tr -d '[:space:]')"
TBL_ARR+=("$i")
fi
done
for t in ${TBL_ARR[#]}; do
showTbl $t
done
This successfully shows me that ${TBL_ARR[#]} has all the values from the query result.
results=($( mysql –uroot –ppwd –se "SELECT * from users" ))
if [ "$?" -ne 0 ]
then
echo fail
exit
fi