mysqldump avoid file creation if no results - mysql

I try to make a differential backup from last backup like this:
mysqldump --no-create-info --replace --skip-comments --skip-triggers --hex-blob
testdb mytable --where="last_backup > '$last_backup'" | gzip -c > backup_file.gz
All ok but if no changes from the last backup mysqldump get one empty file (only header and footer lines specific to mysql)
Is there a way to avoid the creation of backup_file.gz if no changes?
SOME LIKE:
IF ((SELECT COUNT(*) FROM my_table WHERE last_backup > '$last_backup') > 0) THEN
mysqldump --no-create-info --replace --skip-comments --skip-triggers --hex-blob
testdb mytable --where="last_backup > '$last_backup'" | gzip -c > backup_file.gz

Finally I have solved with this:
if [[ "$(mysql -sse 'USE my_bd; SELECT COUNT(*) FROM my_table WHERE last_backup > '$last_backup'" -gt "0" ]]; then
mysqldump --no-create-info --replace --skip-comments --skip-triggers --hex-blob
testdb mytable --where="last_backup > '$last_backup'" | gzip -c > backup_file.gz
fi
The mysqldump command must be in one line. I have splited to be more readable
But the If condition can be in multiple lines

Related

How to take databse dump of ABC database of table XYZ and only of organization_id "22"?

Lets Say I have database named ABC.
And tables X,Y,Z,M,N which has organization_id 0-50.
How is it possible to create a dump file for tables X,Y,Z with only organization_id=22 ?
You could go through table by table and do
mysqldump -uroot -p db_name table_name --where='id=22'
or you can use
SELECT * INTO OUTFILE 'data_path.sql' from table where id=22
using mysqldump tool you can do that , as you mentioned your database is ABC , and tables are X,Y,Z.hope this works for you.
mysqldump -u db_user -p ABC X Y Z --no_create_info \
--lock-all-tables --where 'organization_id \
in (SELECT X.organization_id FROM X \
JOIN Y ON X.organization_id = Y.organization_id \
JOIN Z ON Y.organization_id = Z.organization_id \
WHERE X.organization_id = 22)' > data.sql

Loop through result set of mysql in Bash

I have a simple bash script. I wish to get an exact count of the number of rows in each table of the database.
#!/bin/bash
TABLES_OLD=$( mysql -u user -ppassword MySchema --batch --skip-column-names -e"SHOW TABLES FROM MySchema" )
for table in "${TABLES_OLD[#]}"
do
QUERY="SELECT COUNT(*) FROM ${table}"
echo "${QUERY}"
done
The script prints:
SELECT COUNT(*) FROM Table 1
Table2
Table3
Table4
etc...
Clearly this is not what I want, and I don't even understand how what is happening is possible. What am I doing wrong?
Try this, put the tables into an array then loop thru the results
db_host='host'
db_user='user'
db_pass='password'
db='your_db'
read -ra var_id <<< $(mysql -h $db_host -u $db_user -p$db_pass $db -sse "show tables from $db")
for i in "${var_id[#]}";
do
results=$(mysql -h $db_host -u $db_user -p$db_pass $db -sse "select count(*)from $i")
echo "$i $results"
done
This should do it :
#/bin/bash
mysql -u user-ppassword -e "SELECT table_name, table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'your_data_base_name';"
Replace echo with eval
The code will be
#!/bin/bash
TABLES_OLD=$( mysql -u user -ppassword MySchema --batch --skip-column-names -e"SHOW TABLES FROM MySchema" )
for table in "${TABLES_OLD[#]}"
do
QUERY="SELECT COUNT(*) FROM ${table}"
eval "${QUERY}"
done

Bash mysql array do not get empty value

My Bash script makes an array from MySQL:
info_tmp=$(mysql --batch --silent -u root -ppassword database -e "SELECT id,info1,info2 FROM table WHERE id=1")
info=($(for i in $info_tmp;do echo $i;done))
info1=${info[1]}
My problem is, that, if info1 is an empty string in the database, then $info1 became info2.
How can I put an empty string into $info array?
Mysql Database:
Id | info1 | info2
1 | | data2
2 | data3 | data4
$info_tmp
1 data2
2 data3 data4
Thank you for your answer
This is the final code that worked (#Barmar):
IFS="|"
info_tmp=$(mysql --batch --silent -u root -ppassword database -e "SELECT CONCAT_WS('|', id,info1,info2) FROM table WHERE id=1")
info=(${info_tmp// / })
info1=${info[1]}
If there's a character that shouldn't appear in any of the columns, use that as a delimiter.
IFS="|"
info_tmp=$(mysql --batch --silent -u root -ppassword database -e "SELECT CONCAT_WS('|', id,info1,info2) FROM table WHERE id=1")
This works because bash doesn't merge sequences of non-whitespace delimiters in IFS, only whitespace characters.
I'm not sure what the point of the for loop that copies $info_tmp to $info is, but you need to do the same thing there. If you use whitespace as your word delimiter, you'll never be able to get empty array values from command substitution.
What about temporarily adding a single character in your for-loop:
info_tmp=$(mysql --batch --silent -u root -ppassword database -e "SELECT id,info1,info2 FROM table WHERE id=1")
info=($(for i in $info_tmp;do echo " "$i;done))
info1=$(${info[1]} | cut -c 2-)

Declare variable in Bash?

I'm connected to my DB from the bash. I do a select count of an array and I want to stock the return in a variable. How can I do that?
I did:
var=`"select count(*) from shop_tab where catalog <> ''" | mysql -h abcdcef.com --port=3306 --user=root --password=hbbfe shop`
The request return a number but it doesn't stock into the variable.
Thanks!
EDIT: It works with this command line:
myvar = $(echo "select count(*) from shop_tab where catalog <> '';" | mysql -h abcdcef.com --port=3306 --user=root --password=hbbfe shop)
An easier way is :
var=$(mysql -h abcdcef.com --port=3306 --user=root --password=hbbfe --batch --skip-column-names -Dshop -e "select count(*) from shop_tab where catalog <> ''")
Moreover, I'll preconize the use of function in order to easily add options to the MySQL command without having to modifying all your script.
function MysqlQuery() {
mysql -h abcdcef.com --port=3306 --user=root --password=hbbfe --batch --skip-column-names -D "$1" -e "$2";
}
va=$(MysqlQuery Shop "SELECT COUNT(*) FROM shop_tab WHERE catalog <> ''")
vaABC=$(MysqlQuery Shop "SELECT COUNT(*) FROM shop_tab WHERE catalog <> 'abc'")
vadef=$(MysqlQuery Shop "SELECT COUNT(*) FROM shop_tab WHERE catalog <> 'def'")
# ...
I find this more readable too...
I think you are forgetting an echo in the pipe? Like this:
var=`echo "select count(*) from shop_tab where catalog <> ''" | mysql -h abcdcef.com --port=3306 --user=root --password=hbbfe shop`

Easiest way to get count val from mysql in bash

Maybe i should use python or perl but i dont know any.
I have 4 statements and i would like to check if there are any errors longer then an hour. My user is setup so i dont need to enter a mysql user/pass. This statement is in mysql_webapp_error_check.sh
#!/bin/bash
mysql testdb -e "select count(*) from tbl where last_error_date < DATE_SUB(NOW(), INTERVAL 1 HOUR);"
How do i make it give me the return value (count(*)) instead of printing to screen?
Then i'll write an if statement and output to stdout/err for cron to use to email me (otherwise i want the script to be silent so nothing is emailed unless theres a problem)
Searched the same, -s for silent works exactly for me.
#!/bin/bash
result=`mysql testdb -s -e "select count(*) from tbl where last_error_date < DATE_SUB(NOW(), INTERVAL 1 HOUR);"`
echo result = .$result.
PS.: There is also a --batch parameter in my mysql Ver 14.14 Distrib 5.1.49 which "Write fields without conversion. Used with --batch" so its a little off-topic here, but should be mentioned here.
in bash, you use $() syntax.
#!/bin/bash
ret=$(mysql testdb -e "select count(*) from tbl where last_error_date < DATE_SUB(NOW(), INTERVAL 1 HOUR);")
if [[ "$ret" > 0 ]];then
echo "there is count"
else
echo "no count"
fi
I usually do this:
var=`mysql -e "SELECT COUNT(*) FROM ...\G" | awk '/COUNT/{print $2}/'`
For my part I simply use grep -v to exclude the line printing count(*) from the return of MySQL.
So I get the counter like that:
db_name="NAME_DB";
db_user="USER_DB";
db_pwd="PWD_DB";
counter=`mysql -u${db_user} -p${db_pwd} ${db_name} -e "SELECT count(*) FROM my_table WHERE something = '1';" | grep -v "count"`;
echo "Count for request: $counter";
I use it for some Wordpress stuff this way, reading databases infos from the wp-config.php file:
wp_db_infos="wp-config.php";
wp_db=`cat ${wp_db_infos} | grep "DB_NAME" | awk -F ', ' '{print $2}' | awk -F "'" '{print $2}'`;
wp_user=`cat ${wp_db_infos} | grep "DB_USER" | awk -F ', ' '{print $2}' | awk -F "'" '{print $2}'`;
wp_pwd=`cat ${wp_db_infos} | grep "DB_PASSWORD" | awk -F ', ' '{print $2}' | awk -F "'" '{print $2}'`;
img_to_update=`mysql -u${wp_user} -p${wp_pwd} ${wp_db} -e "SELECT count(*) FROM wp_offres WHERE maj_img = '1';" | grep -v "count"`;
#!/bin/bash
echo show databases\; | mysql -u root | (while read x; do
echo "$x"
y="$x"
done
echo "$y"
)
local count=$(mysql -u root --disable-column-names --batch --execute "SELECT COUNT(*) FROM mysql.user WHERE user = '$DstDbName'")
if [[ "$count" > 0 ]]
then
fi
--batch - do clear output w/o borders
--disable-column-names - prints only row with value
no creasy AWK used :)