BASH: Assigning MySQL SELECT result elements to different variables - mysql

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

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'

How to check if a table exists in a MySQL database using shell script?

i am trying to check whether a table is empty or not using shell script
the code that i have is
#!/bin/bash
if [ "mysql -u user -ppassword -hserver dbname -e 'select count(*) from test_dec;'" != 0 ];
then
echo "table not empty"
else
echo "table empty"
fi
but when i run this it always displays "table not empty" even if the output of the query is 0.
user#server$ ./table_check.sh
table not empty
what is wrong here?
This is my version of the script and it will first check if table exists and if yes will check if the table is empty.
BASH
#!/bin/bash
# Prepare variables
TABLE=$1
SQL_EXISTS=$(printf 'SHOW TABLES LIKE "%s"' "$TABLE")
SQL_IS_EMPTY=$(printf 'SELECT 1 FROM %s LIMIT 1' "$TABLE")
# Credentials
USERNAME=YOUR_USERNAME
PASSWORD=YOUR_PASSWORD
DATABASE=YOUR_DATABASE_NAME
echo "Checking if table <$TABLE> exists ..."
# Check if table exists
if [[ $(mysql -u $USERNAME -p$PASSWORD -e "$SQL_EXISTS" $DATABASE) ]]
then
echo "Table exists ..."
# Check if table has records
if [[ $(mysql -u $USERNAME -p$PASSWORD -e "$SQL_IS_EMPTY" $DATABASE) ]]
then
echo "Table has records ..."
else
echo "Table is empty ..."
fi
else
echo "Table not exists ..."
fi
USAGE
First before using this script you need to replace YOUR_USERNAME, YOUR_PASSWORD and YOUR_DATABASE_NAME with the corresponding values. Then:
# bash SCRIPT_NAME TABLE_TO_CHECK
bash my_script my_table
where SCRIPT_NAME( my_script ) is the name of the file holding the above script content and TABLE_TO_CHECK( my_table ) is the name of the table that you want to check for.
EXPECTED OUTPUT
Checking if table <my_table> exists ...
Table exists ...
Table is empty ...
COUPLE OF WORDS ABOUT THE CODE
Store the first argument from the command line in variable TABLE
TABLE=$1
Prepare two variables that will hold the SQL queries used to check.
Note that printf is used to insert the table name in the variables, because $('SHOW TABLES LIKE "$TABLE"') is not going to work.
SQL_EXISTS=$(printf 'SHOW TABLES LIKE "%s"' "$TABLE")
SQL_IS_EMPTY=$(printf 'SELECT COUNT(*) as records FROM %s' "$TABLE")
Check if table exists. SHOW TABLES LIKE "table_name" will return empty string if the table does not exist and the if statement will fail. Usage of the $ like $(echo 1 + 2) means - evaluate whatever is inside the parentheses and return that as a value.
if [[ $(mysql -u $USERNAME -p$PASSWORD -e "$SQL_EXISTS" $DATABASE) ]]
Finally we check if table is empty. Using the previous approach. Basically we check if MySQL will return empty string (for empty tables), otherwise the query will return some text as a result and we can consider the table not empty.
if [[ $(mysql -u $USERNAME -p$PASSWORD -e "$SQL_IS_EMPTY" $DATABASE) ]]
This should work
if [ $(mysql -u root -p -e \
"select count(*) from information_schema.tables where \
table_schema='db_name' and table_name='table_name';") -eq 1 ]; then
echo "table exist"
exit 1
else
echo "table doesn't exist"
exit 1
fi
I think below will do your work,
#!/bin/bash
if [ $(mysql -u user -ppassword -hserver dbname -sse "select count(*) from test_dec;") -gt 0 ];
then
echo "table not empty"
else
echo "table empty"
fi
3 changes from your script,
enclose whole mysql statement part inside $(..) --> to make LHS the result of what goes inside $(...)
change -e to -sse in mysql connection statement --> to get only result of query to output without header and table structure.
Change != to -gt --> operator for integer comparison in bash
This works for me when testing if we need to re-import a database.
databasename="mydatabasename";
tablename="tableweneed";
dbhost="localhost";
username="user";
password="password";
dbtest=$(mysql -h ${dbhost} -u ${username} -p${password} -s -N -e "select count(*) as tablecount from information_schema.tables WHERE table_schema='${databasename}' and table_name='${tablename}'")
if [ "$dbtest" == 1 ]; then
echo "Database is ok"
else
echo "Database is being re-imported"
mysql -h ${dbhost} -u ${user} -p${password} ${databasename} < /somefolderonmysystem/importdb.sql
fi
After trying a few different methods, this is what we used:
if [[ $(mysql --execute "SHOW TABLES FROM ${DB_NAME} LIKE '${DB_PREFIX}options';") -gt 0 ]]; then
...and yes, we define mysql as a function earlier in the script, and the database name and database prefix are also defined in a configuration file (this is part of our SlickStack project).
function mysql {
command mysql --user=root --host=localhost --protocol=socket --port=3306 --force "$#"
}
You can change the name of this function in your bash script as desired.
Example: https://github.com/littlebizzy/slickstack/blob/master/bash/ss-install-wordpress-config.txt

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.

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

Bash script: Mysql query field to variable

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//,}