MySQL syntax error regarding WHERE NOT EXISTS - mysql

I have a Chef recipe for creating Unix user IDs and deploying them across multiple nodes, to guarantee uniqueness and prevent devs from having to track them themselves. They merely name the application and it is granted a unique ID if an ID for that application doesn't already exist. If one does, it is simply returned to the script and user accounts are created on the webservers with the appropriate value.
I have a mysql database with a single table, called application_id_table which has two columns, id and application_name. id is autoincrementing and application name cannot be null (and must be unique).
Removing the Ruby from my script and making a couple of substitutions, my sql looks like this:
INSERT INTO application_id_table(application_name) VALUES('andy_test')
WHERE NOT EXISTS (select 1 from application_id_table WHERE
application_name = 'andy_test');
when run, I receive the syntax parsing error:
ERROR 1064 (42000): 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 'WHERE NOT EXISTS (select 1 from
application_id_table WHERE application_name = 'a'
I recall seeing that the values statement does not allow a where clause but I don't wish to use a select statement to populate the values as I'm populating them from variables supplied from within Ruby/Chef. Anyone have an idea how to accomplish this?

You want to use insert . . . select:
INSERT INTO application_id_table(application_name)
SELECT aname
FROM (SELECT 'andy_test' as aname) t
WHERE NOT EXISTS (select 1 from application_id_table ait WHERE ait.application_name = t.aname);
You should be able to plug your variable directly into the select statement, the same you would would with the VALUES statement.

Try this:
INSERT INTO application_id_table(application_name)
select 'andy_test'
WHERE NOT EXISTS (select 1 from application_id_table WHERE application_name = 'andy_test');

Related

A variable is cut in a wrong way but now sure why?

I'm writing a script that locates all branches of a specific repo that haven't received any commits for more than 6 months and deletes them (after notifying committers).
This script will run from Jenkins every week, will store all these branches in some MySQL database and then in the next run (after 1 week), will pull the relevant branch names from the database and will delete them.
I want to make sure that if for some reason the script is run twice on the same day, relevant branches will not get added again to the database, so I check it using a SQL query:
def insert_data(branch_name):
try:
connection = mysql.connector.connect(user=db_user,
host=db_host,
database=db_name,
passwd=db_pass)
cursor = connection.cursor(buffered=True)
insert_query = """insert into {0}
(
branch_name
)
VALUES
(
\"{1}\"
) where not exists (select 1 from {0} where branch_name = \"{1}\" and deletion_date is NULL) ;""".format(
db_table,
branch_name
)
cursor.execute(insert_query, multi=True)
connection.commit()
except Exception as ex:
print(ex)
finally:
cursor.close()
connection.close()
When I run the script, for some reason, the branch_name variable is cut in the middle and then the query that checks if the branch name already exists in the database fails:
1064 (42000): 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 'where not exists (select 1 from branches_to_delete where branch_name = `AUT-1868' at line 8
So instead of checking for 'AUT-18681_designer_create_new_name_if_illegal_char_exist' it checks for 'AUT-1868' which doesn't exist in the database.
I've tried the following:
'{1}'
"{1}"
{1}
But to no avail.
What am I doing wrong?
Using WHERE statement in INSERT INTO query is illegal:
INSERT INTO `some_table`(`some_column`)
VALUES ('some_value') WHERE [some_condition]
So, the above example is not valid MySQL query. For prevent duplication of branch_name you should add unique index on your table like:
ALTER TABLE `table` ADD UNIQUE INDEX `unique_branch_name` (`branch_name`);
And after this you can use next query:
INSERT INTO `table` (`branch_name`) VALUES ('branch_name_1')
ON DUPLICATE KEY UPDATE `branch_name` = `branch_name`;
Pay attention: If your table have auto-increment id, it will be incremented on each insert attempt
Since MySQL 8.0 you can use JASON_TABLE function for generate pseudo table from your values filter it from already exists values and use it fro insert. Look here for example
I don't see anything wrong assuming the source of the branch_name is safe (you are not open to SQL Injection attacks), but as an experiment you might try:
insert_query = f"""insert into {db_table}(branch_name) VALUES(%s) where not exists
(select 1 from {db_table} where branch_name = %s and deletion_date is NULL)"""
cursor.execute(insert_query, (branch_name, branch_name))
I am using a prepared statement (which is also SQL Injection-attack safe) and thus passing the branch_name as a parameters to the execute method and have also removed the multi=True parameter.
Update
I feel like a bit of a dummy for missing what is clearly an illegal WHERE clause. Nevertheless, the rest of the answer suggesting the use of a prepared statement is advice worth following, so I will keep this posted.

MySQL vs. MariaDB - same update...select fails in MariaDB

I'm implementing a search on a simple database with about 7 relevant fields. The idea is to CONCAT the 7 fields and find the search term using the LIKE operator. Records that don't match have a flag (filter) that's set to zero.
UPDATE mapping SET FILTER = 0 WHERE id IN(
SELECT id WHERE
CONCAT(Field1, Field2, F3, F4, F5, F6, F7) NOT LIKE "%searchTerm%"
);
This works like a charm on my local dev with MySQL.
But, my host uses MariaDB and I get an error message:
#1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use
near 'WHERE CONCAT( targets, organizations, ' at line 4.
I've isolated the SELECT statement (and added from mapping), and that works, too. But, the update only works locally, not on a live site.
I've been wracking my brains since last night. Any ideas?
You need to remove subquery because it is unnecessary:
-- works on MySQL/MariaDB
UPDATE mapping
SET FILTER = 0
WHERE CONCAT(F1, F2) NOT LIKE '%searchTerm%';
If you want to use IN operator as you proposed then you have to use FROM clause:
-- this will work only in MariaDB
UPDATE mapping
SET FILTER = 0
WHERE id IN(SELECT id FROM mapping WHERE CONCAT(F1, F2) NOT LIKE '%searchTerm%');
db<>fiddle demo Maria DB 10.3
And to help MySQL:
UPDATE mapping
SET FILTER = 0
WHERE id IN(SELECT id -- note additional subquery
FROM (SELECT id FROM mapping
WHERE CONCAT(F1, F2) NOT LIKE '%searchTerm%') sub);
db<>fiddle demo - MySQL
Related article: You can't specify target table for update in FROM clause

Making a backup copy of SQL table throws me this error: "#1064 - You have an error in your SQL syntax; "

I'm trying to make a backup of my table in MySql but I get this error:
#1064 - 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 'table `zbackup_oc_t_city` from `oc_t_city` LIMIT 0, 30' at line 1
This is the code that I'm using to backup
SELECT * INTO TABLE `zbackup_oc_t_city` FROM `oc_t_city`
Here is my oc_t_city table:
Here is zbackup_oc_t_city
I have tried it on numerous tables and it keeps throwing me the same error... any ideas?
Thanks
If you want to create your backup table and do the backup in just one statement use
CREATE TABLE `zbackup_oc_t_city` SELECT * FROM `oc_t_city`;
CREATE TABLE ... SELECT Syntax
You can create one table from another by adding a SELECT statement at
the end of the CREATE TABLE statement:
CREATE TABLE new_tbl [AS] SELECT * FROM orig_tbl;
With MySQL you can't use SELECT ... INTO to select into a new table:
SELECT ... INTO Syntax
The SELECT ... INTO form of SELECT enables a
query result to be stored in variables or written to a file:
SELECT ... INTO var_list selects column values and stores them into
variables.
SELECT ... INTO OUTFILE writes the selected rows to a file. Column and
line terminators can be specified to produce a specific output format.
SELECT ... INTO DUMPFILE writes a single row to a file without any
formatting.
I do remember having similar troubles while working with SQL myself. One cause of error I found was the use of citation marks... try removing the citation marks like this:
SELECT * INTO zbackup_oc_t_city FROM oc_t_city;
I'm not sure this fixes your problem (but I can't see anything else wrong with your query). I hope it does though. :)

Multiple Queries in Triggers

I'm fairly new to using triggers and have a tiny question.
I have a trigger finds a match between a newly inserted enquiry and a customer table.
INSERT INTO customersmatched (customerID,enquiryID) SELECT id, NEW.id FROM customer AS c WHERE c.customerName=NEW.companyName HAVING COUNT(id)=1;
I then need to update the newly inserted enquiry so it has a status which shows it's matched (but only if it has matched). So I tried adding this line after the insert.
UPDATE enquiry SET status="Live-Enquiry" WHERE id IN ( SELECT enquiryID FROM customersmatched WHERE enquiryID = NEW.id);
Except I get this error:
MySQL said: #1064 - 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 'UPDATE enquiry SET status="Live-Enquiry" WHERE id
IN ( SELECT enquiryID FROM cus' at line 5
How do I allow multiple queries within a trigger. I've tried doing something like in this link: Multiple insert/update statements inside trigger?
But doesn't work either. I'm using phpmyadmin btw. Can anyone help? :D
If you have ansi quotes enabled then you can't use double quotes as a string literal, and need to use single quotes instead. see: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_ansi_quotes Otherwise, I don't see any syntax errors that jump out at me.
Try changing SET status="Live-Enquiry" to SET status='Live-Enquiry'
EDIT:
What is the purpose of the first query? I'm not sure you need the HAVING in that query. If want a distinct list of matches, just use DISTINCT
INSERT INTO customersmatched (customerID,enquiryID)
SELECT DISTINCT id, NEW.id
FROM customer AS c
WHERE c.customerName=NEW.companyName;
The second query, if I understand it correctly, can be simplified to this:
UPDATE enquiry
SET status='Live-Enquiry'
WHERE id = NEW.id;

delete query for mysql using c

can anyone tell me the correct query to delete values from mysql db table,in my case the table name and id are accepted from the user and the row is deleted based on id.This is my query
sprintf(Query,"DELETE FROM ('%s') where id = (%d)",tb1,idt1) ;
/*table name is in form of string and id is int */
mysql_query(conn,Query);
You should remove parentheses around the table name:
sprintf(Query,"DELETE FROM '%s' where id = (%d)",tb1,idt1) ;
MySQL considers queries like this syntax errors:
delete from (mytable) where id=2;
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 '(mytable) where id=2' at line 1
(I'll assume that you know everything about SQL injection attacks, and that neither tb1 nor idt1 are constructed from user input in any shape or form).