Bash Script Evaluate String Problems - mysql

I'm trying to create a script to automatically delete all of the tables from a database using shell.
The commented out variable $drop works fine, however when I try to substitute in the table
for table in $tables
do
command="'drop table ${table}'"
# drop=$(${login} -e 'drop table test') -- this works fine
drop=$(${login} -e $command)
echo $drop
# echo -e "Removed table ${table}"
done

(major edit)
The issue is with your use of quotes. In your code, since you do not quote $command it is subject to word splitting by the shell. The $login command receives these arguments: "-e", "'drop", "table", "table_name'" -- note the stray single quotes in the second and last elements.
Do this:
command="drop table $table"
drop=$($login -e "$command")

Related

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.

only a string is returned in a mysql query in a bash script

There's plenty of similar questions out there that seem to answer this, but it's not working for me.
Here's mysql query in a bash script, the resultant row comes back as a string, not as an array.
Am I missing something?
while read -a row;
do
echo "${row[0]}";
done < <(mysql -u $dbuser -p$dbpass -N --database=$dbname --host=$dbhost --batch -se "SELECT id, CONCAT(id, '_', filename) from photos" );
}
This echoes 200 200_filename.jpg.
I would think it is supposed to echo 200.
Echoing ${row[1]} displays a blank line.
And the magic spell is the IFS. Adding that in with the tab fixes the array issue
while IFS=$'\t' read -a row;
do
echo "${row[0]}";
done

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

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

dumping data from views in mysql

i have a view and want to extract its data into a file that has create table statement as well data.
i know that mysqldump doesn't work on views.
Obviously, there isn't an automated way to generate the CREATE TABLE statement of a table that does not exist. So you basically have two options:
Create an actual table, dump it and remove it afterwards.
Write a lot of code to analyse the view and underlying tables and generate the appropriate SQL.
First option is not optimal at all but it's easy to implement:
CREATE TABLE my_table AS
SELECT *
FROM my_view
You can now dump the table with mysqldump. When you're done:
DROP TABLE my_table
Second option can be as optimal as you need but it can get pretty complicate and it depends a lot on your actual needs and tool availability. However, if performance is an issue you can combine both approaches in a quick and dirty trick:
CREATE TABLE my_table AS
SELECT *
FROM my_view
LIMIT 1;
SHOW CREATE TABLE my_table;
Now, you use your favourite language to read values from my_view and build the appropriate INSERT INTO code. Finally:
DROP TABLE my_table;
In any case, feel free to explain why you need to obtain SQL code from views and we may be able to find better solutions.
Use SELECT ... INTO OUTFILE to create a dump of the data.
I have written a bash function to export the "structure" and data of a VIEW without creating a full copy of the data. I tested it with MySQL 5.6 on a CentOS 7 server. It properly takes into account columns with JSON values and strings like "O'Mally", though you may need to tweak it further for other special cases.
For the sake of brevity, I did not make it robust in terms of error checks or anything else.
function export_data_from_view
{
local DB_HOST=$1
local SCHEMA=$2
local VIEW=$3
local TMP_TABLE_NAME="view_as_table_$RANDOM"
local SQL1="
create table $TMP_TABLE_NAME as
(select * from $VIEW where 1=0);
show create table $TMP_TABLE_NAME \G
"
# Create an empty table with the structure of all columns in the VIEW.
# Display the structure. Delete lines not needed.
local STRUCT=$(
mysql -h $DB_HOST -BANnq -e "$SQL1" $SCHEMA |
egrep -v "\*\*\*.* row \*\*\*|^${TMP_TABLE_NAME}$" |
sed "s/$TMP_TABLE_NAME/$VIEW/"
)
echo
echo "$STRUCT;"
echo
local SQL2="
select concat( 'quote( ', column_name, ' ),' )
from information_schema.columns
where table_schema = '$SCHEMA'
and table_name = '$VIEW'
order by ORDINAL_POSITION
"
local COL_LIST=$(mysql -h $DB_HOST -BANnq -e "$SQL2")
# Remove the last comma from COL_LIST.
local COL_LIST=${COL_LIST%,}
local SQL3="select $COL_LIST from $VIEW"
local INSERT_STR="insert into $VIEW values "
# Fix quoting issues to produce executeable INSERT statements.
# \x27 is the single quote.
# \x5C is the back slash.
mysql -h $DB_HOST -BANnq -e "$SQL3" $SCHEMA |
sed '
s/\t/,/g; # Change each TAB to a comma.
s/\x5C\x5C\x27/\x5C\x27/g; # Change each back-back-single-quote to a back-single-quote.
s/\x27NULL\x27/NULL/g; # Remove quotes from around real NULL values.
s/\x27\x27{/\x27{/g; # Remove extra quotes from the beginning of a JSON value.
s/}\x27\x27/}\x27/g; # Remove extra quotes from the end of a JSON value.
' |
awk -v insert="$INSERT_STR" '{print insert "( " $0 " );"}'
local SQL4="drop table if exists $TMP_TABLE_NAME"
mysql -h $DB_HOST -BANnq -e "$SQL4" $SCHEMA
echo
}

Create table if not exists from mysqldump

I'm wondering if there is any way in mysqldump to add the appropriate create table option [IF NOT EXISTS]. Any ideas?
Try to use this on your SQL file:
sed 's/CREATE TABLE/CREATE TABLE IF NOT EXISTS/g' <file-path>
or to save
sed -i 's/CREATE TABLE/CREATE TABLE IF NOT EXISTS/g' <file-path>
it's not ideal but it works :P
According to one source, mysqldump does not feature this option.
You could use the --force option when importing the dump file back, where MySQL will ignore the errors generated from attempts to create duplicate tables. However note that with this method, other errors would be ignored as well.
Otherwise, you can run your dump file through a script that would replace all occurrences of CREATE TABLE with CREATE TABLE IF NOT EXISTS.
Using sed as described by #Pawel works well. Nevertheless you might not like the idea of piping your data through more potential error sources than absolutely necessary. In this case one may use two separate dumps:
first dump containing table definitions (--no-data --skip-add-drop-table)
second dump with only data (--no-create-info --skip-add-drop-table)
There are some other things to take care of though (e.g. triggers). Check the manual for details.
Not what you might want, but with --add-drop-table every CREATE is prefixed with the according DROP TABLE statement.
Otherwise, I'd go for a simple search/replace (e.g., with sed).
The dump output is the combination of DROP and CREATE, so you must remove DROP statement and change the CREATE statement to form a valid (logical) output:
mysqldump --no-data -u root <schema> | sed 's/^CREATE TABLE /CREATE TABLE IF NOT EXISTS /'| sed 's/^DROP TABLE IF EXISTS /-- DROP TABLE IF EXISTS /' > <schema>.sql
create a bash script with this...
make sure you make it executable. (chmod 0777 dump.sh)
dump.sh
#!/bin/bash
name=$HOSTNAME
name+="-"
name+=$(date +"%Y-%m-%d.%H:%M")
name+=".sql"
echo $name;
mysqldump --replace --skip-add-drop-table --skip-comments izon -p > "$name"
sed -i 's/CREATE TABLE/CREATE TABLE IF NOT EXISTS/g' "$name"
The sed will be much faster without the 'g' (global) at its end:
eg:
mysqldump -e <database> | sed 's/^CREATE TABLE /CREATE TABLE IF NOT EXISTS /' > <database>.sql
To Find and replace the text On Windows 7 Using PowerShell
Open command prompt and use the command below
powershell -Command "(gc E:\map\map_2017.sql) -replace 'CREATE TABLE', 'CREATE TABLE IF NOT EXISTS' | Out-File E:\map\map_replaced.sql"
First param is the filepath
Second param is 'find string'
Third param is 'replace string'
This command will create a new file with the replaced text.
Remove the Command starting from '|' (pipe) if you want to replace and save contents on the same file.