Add multi line string from variable into mysql with bash - mysql

I'm running a python script which returns several lines of text, which I use the following truncate command tr and want to add to my database.
I start here: this removes the unformatted line delimiters.
tr -d '\15\32' < long_text > unixfile.txt
I'm then left with an output which looks like this:
Happy Birthday Stackoverflow
Happy Birthday to you
Happy Birthday Stackoverflow
I use the following command to place this into a variable:
lyrics=$(cat unixfile.txt)
mysql --user=USER --password=PASSWORD --database='DB' --execute='INSERT INTO `song_lyrics` (`id`, `song_id`, `lyrics`, `info`) VALUES ('"'$i'"', '"'$i'"', '"$lyrics"', '0');'
ERROR 1064 (42000) at line 1:
It seems that MySQL is seeing my entire 3 line string (shown above) in three different commands, because the output of the unixfile.txt appears in the error output.

This problem can be solved using the following:
Ensure the long text string is being captured in a file, instead of a variable - then re-capture the file/variable.
lyrics=$(cat unixfile.txt)
mysql --user="$user" --password="$password" --database="$my_db" <<END
use my_db;
INSERT INTO song_lyrics (id, song_id, lyrics, info) VALUES ("$i", "$i", "$lyrics", '0');
END
this method ensures the variable is passed properly.
the only remaining issues would be with various types of punctuation
although this post does not describe this.

Related

mysql - copy from one database to another

I'm trying to copy data from one DB into another on the same server. For this I'm using a bash script:
mysql -uroot -pMYPW -D "ucb-pvapp" -e "insert into app_daily_quartiles (postcode, lo_limit, hi_limit, median) select (PLZ, loLimit, hiLimit, median) from solarlogmesswerte.tagesquartilekleinraum2"
I tried using the dbDest.table notation for the destination too but that gave me an error.
Now I get. ERROR 1241 (21000) at line 1: Operand should contain 1 column(s)
But I'm not able to find the error.
Using version: 8.0.23-0ubuntu0.20.04.1
Remove brackets from select.
So it should go like
insert into app_daily_quartiles (postcode, lo_limit, hi_limit, median)
select PLZ, loLimit, hiLimit, median from solarlogmesswerte.tagesquartilekleinraum2

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

Mysql query to update multiple rows using a input file from linux

I'm trying to update multiple rows in a DB using a small script.
I need to update the rows based on some specific user_ids which I have in a list on Linux machine.
#! /bin/bash
mysql -u user-ppassword db -e "update device set in_use=0 where user_id in ()";
As you see above, the user_ids are in a file, let's say /opt/test/user_ids_txt.
How can I import them into this command?
This really depends on the format of user_ids_txt. If we assume it just happens to be in the correct syntax for your SQL in statement, the following will work:
#! /bin/bash
mysql -u user-ppassword db -e "update device set in_use=0 where user_id in ($(< /opt/test/user_ids_txt))";
The bash interpreter will substitute in the contents of the file. This can be dangerous for SQL queries, so I would echo out the command on the terminal to make sure it is correct before implementing it. You should be able to preview your SQL query by simply running the following on the command line:
echo "update device set in_use=0 where user_id in ($(< /opt/test/user_ids_txt))"
If your file is not in the SQL in syntax you will need to edit it (or a copy of it) before running your query. I would recommend something like sed for this.
Example
Let's say your file /opt/test/user_ids_txt is just a list of user_ids in the format:
aaa
bbb
ccc
You can use sed to edit this into the correct SQL syntax:
sed 's/^/\'/g; s/$/\'/g; 2,$s/^/,/g' /opt/test/user_ids_txt
The output of this command will be:
'aaa'
,'bbb'
,'ccc'
If you look at this sed command, you will see 3 separate commands separated by semicolons. The individual commands translate to:
1: Add ' to the beginning of every line
2: Add ' to the end of every line
3: Add , to the beginning of every line but the first
Note: If your ID's are strictly numeric, you only need the third command.
This would make your SQL query translate to:
update device set in_use=0 where user_id in ('aaa'
,'bbb'
,'ccc')
Rather than make a temporary file to store this, I would use a bash variable, and simply plug that into the query like this:
#! /bin/bash
in_statement="$(sed 's/^/\'/g; s/$/\'/g; 2,$s/^/,/g' /opt/test/user_ids_txt)"
mysql -u user-ppassword db -e "update device set in_use=0 where user_id in (${in_statement})";

SQL Syntax Error from bash script

I have a script that essentially creates Devices, graphs, and trees as well as attempts to create a user for Cacti graphing software.
I receive the below SQL error when attempting to run the shell script. However copying and pasting the exact same input statement into MySQL directly it accepts the syntax.
ERROR 1064 (42000) at line 3: 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 ''TestName','cf199661b212c55286cf81d9602ce63','0', 'TestFullName','on','on','' at line 1
The below script is how this is implemented
php add_device.php --description=$1 --ip=$2 --community=community --template=5 --ping_method=icmp
mysql -u root cacti -ppassword -e "select id from host where description='$1'" | grep -v id > tempID
php add_tree.php --type=node --node-type=host --tree-id=3 --parent-node=34 --host-group-style=2 --host-id=`cat tempID`
php add_graphs.php --host-id=`cat tempID` --graph-type=ds --graph-template-id=2 --snmp-query-id=1 --snmp-query-type-id=14 --snmp-field=ifOperStatus --snmp-value=Up
mysql -u root cacti -ppassword -e "select MAX(id) FROM user_auth" | grep -v id > tempUserID
Number=`cat tempUserID`
User_IDD= $(($Number + 1))
Host_ID=`cat tempID`
mysql -uroot -ppassword cacti << EOF
INSERT INTO user_auth (id,username,password,realm,full_name,must_change_password,show_tree,show_list,show_preview,graph_settings,login_opts,policy_graphs,policy_trees,policy_hosts,policy_graph_templates,enabled) V
ALUES($User_IDD,'$3','cf199661b212c55286cf81d9602ce630',0,'$4','on','on','on','on','on',1,2,2,2,2,'on');
INSERT INTO user_auth_perms (user_id,item_id,type) VALUES ($User_IDD,$Host_ID,3);
INSERT INTO user_auth_realm (realm_id,user_id) VALUES (7,$User_IDD);
EOF
rm TempUserID
rm TempID
~
The exact SQL insert statements pasted directly into the command line are as follows as an example that functions
INSERT INTO user_auth
(id, username, password, realm, full_name, must_change_password, show_tree, show_list, show_preview, graph_settings, login_opts, policy_graphs, policy_trees, policy_hosts, policy_graph_templates, enabled)
VALUES
( 38,
'Test',
'cf199661b212c55286cf81d9602ce63',
'0',
'TestUser',
'on',
'on',
'on',
'on',
'on',
1,
2,
2,
2,
2,
'on'
);
INSERT INTO user_auth_perms
(user_id, item_id, type)
VALUES (38, 285, 3);
INSERT INTO user_auth_realm
(realm_id, user_id)
VALUES (7, 38);
I've been bashing my head against this for a few days now and I can't quite find what's wrong in my syntax, does anyone see anything outright wrong?
It sounds like what's happening is that you're "running" the script in your head, finding that it works fine, and then getting stuck when the computer doesn't agree.
When debugging, you shouldn't run the script for the computer: don't copy-paste the SQL and then replace the variables with what you think they ought to be.
Instead, let the computer run the script: have it output the SQL and then observe if that matches what you expect.
You can do this by replacing mysql -uroot -ppassword cacti with cat, which will make the script spit out the result instead of executing it. You'll see it's something like this:
INSERT INTO user_auth (id,username,password,realm,full_name, [snip])
VALUES(,'baz','cf199661b212c55286cf81d9602ce630',0,'cow','on','on',[snip]);
And now the problem is more obvious: VALUES(,'baz' is missing its first value.
To solve that problem, you can pay careful attention to unexpected error messages. You'll see that one you're getting is something like:
42: command not found
You should not ignore these kinds of messages. When you copy-paste output to stackoverflow, you should include all output (if it's too long, you should reduce the size of your script and input data, rather than redacting information you don't think is relevant).
You'll find that the error occurs on this line:
User_IDD= $(($Number + 1))
And why is it saying "command not found" instead of assigning to the variable? Because of the space after the =. Assignments in bash can not have spaces around the assignment operator.
Remove the space and try again.
I'm not saying that's sufficient to solve all the problems with your script, but it's a good start.
PS: ShellCheck would have automatically pointed out the bad space.

Using shell script to insert data into remote MYSQL database

I've been trying to get a shell(bash) script to insert a row into a REMOTE database, but I've been having some trouble :(
The script is meant to upload a file to a server, get a URL, HASH, and a file size, connect to a remote mysql database, and insert the data into an existing table. I've gotten it working until the remote MYSQL database bit.
It looks like this:
#!/bin/bash
zxw=randomtext
description=randomtext2
for file in "$#"
do
echo -n *****
ident= *****
data= ****
size=` ****
hash=`****
mysql --host=randomhost --user=randomuser --password=randompass randomdb
insert into table (field1,field2,field3) values('http://www.example.com/$hash','$file','$size');
echo "done"
done
I'm a total noob at programming so yeah :P
Anyway, I added the \ to escape the brackets as I was getting errors. As it is right now, the script is works fine until connects to the mysql database. It just connects to the mysql database and doesn't do the insert command (and I don't even know if the insert command would work in bash).
PS: I've tried both the mysql commands from the command line one by one, and they worked, though I defined the hash/file/size and didn't have the escaping "".
Anyway, what do you guys think? Is what I'm trying to do even possible? If so how?
Any help would be appreciated :)
The insert statement has to be sent to mysql, not another line in the shell script, so you need to make it a "here document".
mysql --host=randomhost --user=randomuser --password=randompass randomdb << EOF
insert into table (field1,field2,field3) values('http://www.site.com/$hash','$file','$size');
EOF
The << EOF means take everything before the next line that contains nothing but EOF (no whitespace at the beginning) as standard input to the program.
This might not be exactly what you are looking for but it is an option.
If you want to bypass the annoyance of actually including your query in the sh script, you can save the query as .sql file (useful sometimes when the query is REALLY big and complicated). This can be done with simple file IO in whatever language you are using.
Then you can simply include in your sh scrip something like:
mysql -u youruser -p yourpass -h remoteHost < query.sql &
This is called batch mode execution. Optionally, you can include the ampersand at the end to ensure that that line of the sh script does not block.
Also if you are concerned about the same data getting entered multiple times and your rdbms getting inconsistent, you should explore MySql transactions (commit, rollback, etc).
Don't use raw SQL from bash; bash has no sane facility for sanitizing the data beforehand. Generate a CSV file and upload that instead.