Executing multiple mysql queries from a shell script in a single statement - mysql

I am trying to execute mysql queries from a shell script. Below are the two queries.The first one seems to work and gets the work done. The second statement fails. The second statement however works if I keep single query instead of two.
mysql-ib -utrial -ptrial! trial -se "SET #bh_dataformat='txt_variable'; SELECT #bh_dataformat"
$(mysql-ib -utrial -ptrial! trial -se "SET #bh_dataformat='txt_variable'; SELECT #bh_dataformat")
The error I get when I execute the second statement is
./test.sh: line 15: txt_variable: command not found

You are using a subshell with $(..). That's why the calling's shell variables like txt_variable are not defined anymore.

Related

MySQL transaction error_count

I'm using MySQL version 5.1.60 and I have a script like the following:
START TRANSACTION;
BEGIN;
USE myDB;
DELETE FROM mytbl WHERE .......
DELETE FROM mytbl2 WHERE ......
....
INSERT INTO mytblN VALUE (.......
UPDATE mytbl SET .....
....
COMMIT;
Now, if any statement fails for any reason the execution of the script stops, I get the error message and I have to issue manually a ROLLBACK; and fix the relevant statement.
This script contains from hundreds to thousands statements and if many fails it is hard to fix each statement one by one.
I'm looking for a way to get all the errors in one shot and to have the transaction to rollback automatically.
Somewhere I found that if I replace the final
COMMIT;
with the following
SELECT IF(##error_count=0,'COMMIT;','ROLLBACK;') INTO #res;
PREPARE stmt FROM #res;
EXECUTE stmt;
and combine it with a
--force
parameter executing the script from command line I would get what I wanted.
Unfortunately I found that the system variable ##error_count 'reset' after each statement, and also the MySQL documentation states it:
error_count
The number of errors that resulted from the last statement that
generated messages. This variable is read only. See Section 14.7.5.17,
“SHOW ERRORS Syntax”.
Is there a way, without using a Stored Procedure, to obtain what I want?
So when I call the script from command line like:
>mysql -u root -p --force < myscript.sql >log.txt 2>&1
I have all the error logged in the log.txt file and the transaction rolled back?
many thanks in advance.

How do I tell linux bash to ignore backticks?

I'm writing a chef recipe that calls the mysql command and executes a query. The problem is that the query passed into this command can have backticks, and I have no control over that. EG I'll do something like this:
execute "update_customer_segment_custom_condition_#{no_space_segment_name}" do
action :run
command "mysql --user=#{user} #{db_name} --execute="CALL someStoredProcedure(\"A String\", \"A QUERY CONTAINING BACKTICKS OVER WHICH I HAVE NO CONTROL THAT NEEDS TO BE PASSED VERBATIM\");"
end
but Bash always complains about the syntax because it tries to interpret the backticks and evaluate. How can I tell it to completely ignore that character?
FYI this is being called inside a chef execute block as a command, hence using # for variables.
You could also use an execute resource in Chef instead of bash. That won't use bash and thus backticks have no special meaning.
EDIT:
To be more specific with the example resource you posted
execute "update_customer_segment_custom_condition_#{no_space_segment_name}" do
command ['mysql', "--user=#{user}", db_name, '--execute="CALL someStoredProcedure(\"A String\", \"A QUERY CONTAINING BACKTICKS OVER WHICH I HAVE NO CONTROL THAT NEEDS TO BE PASSED VERBATIM\");"']
end
The array form for command shuts off any processing by the shell.
this is probably because you build a string with ruby (I dont' know ruby) and then pass it into a shell execute with action run
This already has a problem as your double quotes terminate in middle string:
command "mysql --user=#{user} #{db_name} --execute="CALL someStoredProcedure(\"A String\", \"A QUERY CONTAINING BACKTICKS OVER WHICH I HAVE NO CONTROL THAT NEEDS TO BE PASSED VERBATIM\");"
so I wonder if ruby does not give a syntax error here for the supplemental " at the end.
the string you want to generate looks (probably) like this:
mysql --user=#{user} #{db_name} --execute="CALL someStoredProcedure(\"A String\", \"A QUERY\");"
you need to generate it like that:
mysql --user=#{user} #{db_name} --execute='CALL someStoredProcedure("A String", "A QUERY");"
And the part with "A QUERY" you need to replace all occurences of ' with '\'' else you can still get a shell code injection.

Unix: Passing Param to MYSQL files from BASH Shell Script

I want to pass SOME VARIABLES to mysql file from bash shell script.
Here is my shell script.
#!/bin/bash
echo $0 Started at $(date)
mysql -uroot -p123xyzblabla MyMYSQLDBName<mysqlfile.sql PARAM_TABLE_NAME
Please note that it is MYSQL and not SQLPLUS
My MYSQL.sql , I want to read and use passed parameter/argument (PARAM_TABLE_NAME)
select count(*) from PARAM_TABLE_NAME
Question 1: What is the correct syntax to pass variable(PARAM_TABLE_NAME) to sql file (mysqlfile.sql)?
Question 2: How can I print variable(PARAM_TABLE_NAME) in sql file (mysqlfile.sql)?
Basically, I want to make generic SQL script which can load or select data from tables based on received inputs.
Thanks
There is no such thing as passing a parameter to a SQL file. A SQL file is no more than a text file that contains a list of SQL statements. These statements are interpreted by the mysql client program exactly as if you typed them on your keyboard.
The mysql client does not provide the feature you are looking for.
But I can think of a few tricks to achieve a similar effet:
create/populate a configuration table prior to reading your SQL file. Then write your SQL file so that it takes this table contents into account:
bash> mysql -e "INSERT INTO config_table VALUES(1, 2, 3)"
bash> mysql < script.sql
prepend your SQL file with some variables declarations. Then use these variables in the rest of your script:
bash> (echo "SET #var=123;" ; cat script.sql) |mysql
[example script.sql]
SELECT * FROM mytable WHERE id = #var;
write your SQL file with some placeholders that your replace on the fly, e.g with sed:
bash> sed "s/__VAR_A__/mytable/g" script.sql |mysql
[example script.sql]
SELECT * FROM __VAR_A__ WHERE id = 123;
All the above is quite dirty. A much cleaner solution would involve stored procedures or functions. Then you would just pass your parameters as procedure parameters:
bash> PARAM1='foo'; PARAM2='bar'
bash> mysql -e "CALL MyProc($PARAM1);"
bash> mysql -e "SELECT MyFunc($PARAM2);"
note: it is not possible to parametrize a table name in SQL, so you will need to resort to dynamic SQL like this in all cases (except for the sed-based hack, which I do not recommend)
This is an old thread but I think may still be useful to some people. Something like this should work:
mysql -uroot -p123xyzblabla MyMYSQLDBName -e "set #testVar='customer_name'; source mysqlfile.sql;"
Now #testVar (customer_name) is available for you to use in mysqlfile.sql file.
HTH
The way to pass parameters has already been answered in this or other threads. However, specific to the sample in you question, I'd like to add that you can't use the variables declaration method as a placeholder for a table name, as the documentation says:
User variables are intended to provide data values. They cannot be used directly in an SQL statement as an identifier or as part of an identifier, such as in contexts where a table or database name is expected
If you want to use a table name parameter, you can still use the sed or the stored procedures or functions as answered by #RandomSeed
In addition to that, another way is using PREPARE and EXECUTE in your script. The following example allows you to create a database/schema (in case you wanted to use stored procedures you need to have them already stored in a database), like this:
[myscript.sql]
set #s=CONCAT("CREATE DATABASE ", #dbname);
PREPARE stmt FROM #s;
EXECUTE stmt;
Then use any of the proposed syntax in the other questions to set the #dbname variable:
mysql -uroot -p123xyzblabla MyMYSQLDBName -e "set #dbname='mydatabase'; source myscript.sql;"

Run complex SQL scripts from memo (multi lines)

I'm executing sql scripts while using ADO and MSSQL server .
Under Here you will find an first example of a multi lines sql statement like :
use master;
go;
EXEC sp_detach_db
#dbname=N'DATABASENAME';
go;
I copy these lines from a Tmemo to my TADOQuery.sql.text but fail as already the go statement is not recognized and I get a keyword error by the mssql server.
Can I run the whole sript as one TQquery or do I have th split my query into several pieces, separated by the semicolon and iterate through the whole text ?
At first your code is not valid (no ; after GO) and has to be like this
USE master;
GO
EXEC sp_detach_db
#dbname=N'DATABASENAME';
GO
In fact GO is a delimiter used by MSSMS to separate the SQL-Statements.
If you want to use the same scripts as MSSMS do, you have to work on that like MSSMS.
Split the script into single parts by delimiter GO
Send every part to the Database
You have to split every statement whithout sending go.
SQL-Server is not interpreting GO, this is done by MSSMS.

setting a c-shell variable to a SELECT statement

i have written a c-shell script to connect to a database. This already works just fine and i now want to invoke an sql script to read and print ALL the values in a cetrain table. As of now this is how my script looks
#!/bin/csh
set MYSQL=${MYSQL_HOME}/mysql
${MYSQL} ${CLEDBUSER}
where CLEDBUSER is set as an environment variable like so - CLEADBUSER=-uusername -ppassword -Ddatabasename
i am able to run the script and connect to the database. When i runt he script it gives me the msql pront awaiting the next command. So i added to the script a variable that contains the (SELECT) statement to query the database. Now my script looks like this
#!/bin/csh
set MYSQL=${MYSQL_HOME}/mysql
set SELECTER="SELECT * FROM TB_EARTH_UI;"
${MYSQL} ${CLEDBUSER} ${SELECTER}
the problem is it doesnt return me all the rows and columsn but it returns me a listing of avaiable commands in mysql promt and default options and also vairables and boolean options. Why is my SELECT statement not getting read?
MySQL client (mysql) expects SQL instructions on its standard input (e.g. your keyboard, when invoking from the shell).
You could do: [edit: please ignore, this one is off-topic]
${MYSQL} ${CLEDBUSER} < text_file_of_sql_statements.sql
or
${MYSQL} ${CLEDBUSER} << EOF
${SELECTER}
# you can add other litteral SQL statements here, or more variables containing SQL statements
EOF
or
${MYSQL} ${CLEDBUSER} --execute="${SELECTER}"
[edit]
I totally misunderstood the OP's question. I didn't get it that he was trying to execute SQL statements from a variable. I have edited the above options (thank you outis). Here is another variation:
echo ${SELECTER} | ${MYSQL} ${CLEDBUSER}
Also, the --skip-column-names option could make it easier for you to parse the output.