SQL Errors using like and % - mysql

My script is designed to cycle through environments, hit a database and check to see if any first/last name combination has an associated user ID. I am not sure why I'm getting the error listed below.
#/bin/bash
#specify user to search for *******DO NOT PUT SPACE, ie. jaylefler
echo "Please enter user first name: "
read first_name
echo "Please enter user last name: "
read last_name
echo "Please enter LDAP User ID: "
read ldapuser
echo "Please enter LDAP password: "
stty -echo
read ldappw
stty echo
#logs to write output to
log="ui_${username}_access.log"
finallog="${username}_ui_access.txt"
#create file if not exist, else null it
[[ -f ${log} ]] && cat /dev/null > ${log} || touch ${log}
[[ -f ${finallog} ]] && cat /dev/null > ${finallog} || touch ${log}
#log it all
{
echo "environment"
sshpass -p $ldappw ssh $ldapuser#54.123.777.567 'mysql -h host -u user - ppassword database -e \
"select user_id from users where first like "%'${first_name}'%" and last like "%'${last_name}'%";"'
} > $log
When I execute the script, I receive the following errors:
Please enter user first name:
jay
Please enter user last name:
lefler
Please enter LDAP User ID:
jlefler
Please enter LDAP password:
ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%jay% and last like %lefler%' at line 1
jlefler#ubuntu:~/Desktop$

I'm not that familiar with this type of scripting, but it would seem to me that around %jay% and %lefler% there would need to be quotations so that the SQL appears as:
select user_id from users where first like '%jay%' and last like '%lefler%';

The primary problem in your code is that the quotation marks are inside of the percent signs. :)
The second problem is that you have created something that is vulnerable to SQL injection. I have absolutely no idea how to create bound parameters from a Bash script, but you need to figure that out!

The query to MySQL is supposed to output something like this:
SELECT * FROM pet WHERE name LIKE '%w%';
In bash one of the way to concatenate is as follow:
mystring="some ${string1} arbitrary ${string2} text"
EDIT:
So combining all Plus making somethin to expand the strings inside ''. The problem is that shell Can not expand strings between single quotations marks.
Something like this should work:
CommandFinale=$($sqlCommand -e "select user_id from users where first like '%${first_name}%' and last like '%${last_name}%';")
Then use the variable CommandFinale in you connection chain.
I have not bee able to test it but it should be like that or very similar.

Related

How do you send multiple commands, including an SQL query, via an SSH-Tunnel with Plink? [duplicate]

This question already has answers here:
Escaping parentheses within parentheses for batch file
(4 answers)
Closed 2 years ago.
I am trying to create a Batch file from a Python script which executes Plink to send an SQL-Query to an external Database via SSH. The script would have to activate a batch file with multiple command lines to be sent to the server.
Researching on the internet I have found, that a solution akin to the code snipped below should work.
(
echo command 1
echo command 2
...
) | plink.exe user#hostname -i sshkey.ppk
Entering my commands would yield the following:
(
echo mysql -u admin -pPassword Database
echo INSERT INTO Table VALUES(DEFAULT, (SELECT ID FROM Another_Table WHERE Another_ID = 'foo'), 'bar', 'foobar', 0, 'date', 1);
) | plink.exe user#hostname -i sshkey.ppk
The problem I have is that I am getting the following error: 'bar' can't be processed syntactically at this point. (I am sorry if the translation might be off here, english is not my first language).
I have checked if some special characters have to be escaped, but have not found any conclusive answers. Note, that the first command is correct and works as intended on its own; only the second command seems to be faulty. Would anybody be willing to provide me a solution?
So the answer here is that you need to escape the closing parenthesis TWICE, not only once, and thus have to use three "^" characters. This is because the command inside the brackets is parsed twice and the second "^" needs to be escaped for the first parsing, thus requiring a third character.
See here for details: Escaping parentheses within parentheses for batch file
The code would therefore look like this:
(
echo mysql -u admin -pPassword Database
echo INSERT INTO Table VALUES(DEFAULT, (SELECT ID FROM Another_Table WHERE Another_ID = 'foo'^^^), 'bar', 'foobar', 0, 'date', 1^^^);
) | plink.exe user#hostname -i sshkey.ppk

Creating an SQL file in BASH

I am trying to create an sql script using bash but I keep getting this line after each iteration of my loop
: command not found
This is the case on Ubuntu as well as OSX.
At this stage I am not executing the sql script, I simply trying to create it. What am I missing so that it will not try to "execute" the query?
The queries are fine when tested in phpmyadmin
I don't understand why would need to set the $PATH variable if I am not executing the actual query, I am just creating the text file.
The code I use is:
SQL="";
cat people.txt | while read line
do
PW="my"$line"db";
DB="test_"$line;
$SQL=$SQL"CREATE DATABASE \`$DB\`;CREATE USER \`$line\`#\`localhost\`;SET PASSWORD FOR \`$line\`#\`localhost\` = PASSWORD(\"$PW\") ;GRANT ALL PRIVILEGES ON $DB.* TO \`$line\`#\`localhost\` IDENTIFIED BY \"$PW\";";
done
echo $SQL > t1.sql;
The list I am using for my imports:
bob123
john123
jane123
The output I am getting is:
./02_setup_mysqldb.sh: line 14: =CREATE DATABASE `test_bob123`;CREATEUSER `bob123`#`localhost`;SET PASSWORD FOR `bob123`#`localhost` = PASSWORD("mybob123db") ;GRANT ALL PRIVILEGES ON test_bob123.* TO `bob123`#`localhost` IDENTIFIED BY "mybob123db";: command not found
./02_setup_mysqldb.sh: line 14: =CREATE DATABASE `test_john123`;CREATE USER `john123`#`localhost`;SET PASSWORD FOR `john123`#`localhost` = PASSWORD("myjohn123db") ;GRANT ALL PRIVILEGES ON test_john123.* TO `john123`#`localhost` IDENTIFIED BY "myjohn123db";: command not found
There's an error in your variable assignment, it should be:
SQL=$SQL"CREATE DATABASE...
Note the missing $ in front of the variable name - variables don't need $ in front of the name when values are assigned.
Notes:
1.The assignment to SQL variable is incorrect, just change to SQL="$SQL...", just remove the $ character.
2.When you do cat people.txt | while read LINE, you are ignoring the last line, being necessary to have a blank line after the last line.
3.Your script has a large string concatenation in one line, just create variables to make it more readable.
Finally, code:
#!/bin/bash
while read line
do
PW="my${line}db"
DB="test_$line"
create_database="CREATE DATABASE \`$DB\`;\n"
create_user="CREATE USER \`$line\`#\`localhost\`;\n"
change_password="SET PASSWORD FOR \`$line\`#\`localhost\` = PASSWORD(\"$PW\");\n"
grant_privileges="GRANT ALL PRIVILEGES ON $DB.* TO \`$line\`#\`localhost\` IDENTIFIED BY \"$PW\";\n"
SQL="${SQL}${create_database}${create_user}${change_password}${grant_privileges}"
done < people.txt
echo -e ${SQL} > t1.sql

Detect and delete line break directly out of mysql query

im trying to detect and delete a line break out of a subject (called m.subject) mail information retrieved via CONCAT out of a mysql database.
That said, the linebreak may or may not occur in the subject and therefore must be detected.
My query looks like this:
mysql --default-character-set=utf8 -h $DB_HOST -D $TARGET -u $DB_USER -p$DB_PW -N -r -e "SELECT CONCAT(m.one,';',m.two,';',m.three,';',m.subject,';',m.four';',m.five,';',(SELECT CONCAT(special_one) FROM special_$SQL_TABLE WHERE msg_id = m.six ORDER BY time DESC LIMIT 1)) FROM mails_$SQL_TABLE m WHERE m.rtime BETWEEN $START AND $END AND m.seven = 1 AND m.eight IN (2);"
I tried to delete it afterwards, but getting in performance trouble due to several while operations on all lines already. Is there an easy way to detect and cut it directly via the CONCAT buildup? It is crucial to retrieve only one line after extraction for me.
Updating/changing the database is not an option for me, as I only want to read the current state.

Need to display alternative text when query results return no match

My script cycles through multiple environments and if a user is found, it prints out their ID. The desired output is as follows:
environment1
<user_id>
However, my script is currently working to print out every environment even if there isn't a user id, like follows:
environment1
<user_id>
environment2
environment3
environment4
<user_id>
I would like the code to print out "NO USER FOUND" if the user_id does not exist, rather than excluding the environment altogether.
The code below is what is being utilized:
#log it all
{
echo "environment"
sshpass -p $ldappw ssh $ldapuser#12.345.67.89 'mysql --skip-column-names -hhost -u user -ppassword database -e \
"select user_id from users where first like '"'%${first_name}%' and last like '%${last_name}%';"'"'
} > $log
Any help would be much appreciated for this issue. Unfortunately I'm just beginning to learn more advanced MySQL and Linux command line tools and am not quite proficient enough to know how to handle this problem.
may be
select ifnull(user_id,'NO USER FOUND') from users where first like '"'%${first_name}%' and last like '%${last_name}%';

How to send e-mail to users within a database?

I want to send an e-mail to users within a database.
SQL query:
SELECT nickname, email FROM db_Users;
I want the e-mail to use both columns for example:
To: %email
Hi %nickname,
Message
Can someone show me basic example to do it using a shell script? I just want the basics to know how to get started and not a fully written script :-)
Thanks
Usually I use parameter for replace variables like that. Something like this :
--top of script
NAME=$(mysql -u $USER $DBNAME -p$PWD -sN -e "SELECT nickname FROM db_Users")
EMAIL=$(mysql -u $USER $DBNAME -p$PWD -sN -e "SELECT email FROM db_Users")
echo "${NAME} Message for you" | mail -s "This is the subject" ${EMAIL}
You could do a loop fot each user, including all members in list :
I=0
for i in ${NAME[#]}
do
-- E-mail
I=`expr $I + 1`
done