MySQL IF...ELSE or IF EXISTS statements - mysql

Quick question. I am currently using INSERT... SELECT statement to check a user has a basic member account before they become a coach. This code works fine:
INSERT into coaches (U_Name, P_word, M_ID)
SELECT members.U_Name,members.P_word,members.M_ID FROM members
WHERE members.U_Name="bob1" AND members.P_word="123"
ON DUPLICATE KEY UPDATE U_Name = members.U_Name, P_word = members.P_word;
As you can see I am currently just updating their account with the same data if they already exist. What I want to do now is if the user is a member and has already become a coach, to display a message informing them they are already registered as a coach.
So my question is, do I wrap this in an IF... ELSE statement or do I use an IF EXISTS statement such as this insert if not exists else just select in mysql
Was thinking along the lines of:
IF EXISTS(SELECT coaches.U_Name,coaches.P_word,coaches.M_ID FROM coaches
WHERE coaches.U_Name="bob1" AND coaches.P_word="123")
ELSE
BEGIN
INSERT into coaches (U_Name, P_word, M_ID)
SELECT members.U_Name,members.P_word,members.M_ID FROM members
WHERE members.U_Name="bob1" AND members.P_word="123"
END;
Have also looked at this example here: MySql IF exists select ELSE insert but not sure how I would implement it. Any instructions on where to go from here would be appreciated.

INSERT ... ON DUPLICATE KEY UPDATE Syntax can help you on resolving the issue.
It is available starting on mySQL 5.0
Reference: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

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.

Learning MySQL, Python - Skip Duplicates

I've been trying to learn SQL using python to update a db and am trying to do something simple. Iterate through a csv file that includes the fortune 500 with their revenue info and push into an SQL db. I've run it a few times and it's working great, the only issue is I'm getting duplicates because I've run the same file a few times.
In the future, I'm assuming it's good to learn how to avoid duplicates. After looking around this is what I've found for a proposed solution using WHERE NOT EXISTS but am getting an error. Any advice is welcome as I'm totally new.
Note - I do know I should be updating more than one row at a time, that's my next lesson
import pymysql
import csv
with open('companies.csv','rU') as f:
reader = csv.DictReader(f)
for i in reader:
conn = pymysql.connect(host='host', user='user', passwd='pw', db='db_test')
cur = conn.cursor()
query1 = "INSERT INTO companies (Name, Revenue, Profit, Stock_Price) VALUES (\'{}\',{},{},{})".format(str(i['Standard']),float(i['Revenues']),float(i['Profits']),float(i['Rank']))
query2 = 'WHERE NOT EXISTS (SELECT Name FROM companies WHERE Name = \'{}\')'.format(str(i['Standard']))
query = query1+' '+query2
cur.execute(query)
conn.commit()
cur.close()
OUTPUT:
INSERT INTO companies (Name, Revenue, Profit, Stock_Price) VALUES ('WalMart Stores',469.2,16999.0,1.0) WHERE NOT EXISTS (SELECT Name FROM companies WHERE Name = 'WalMart Stores')
ERROR:
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 Name FROM companies WHERE Name = 'WalMart Stores')' at line 1")
Ok. First of all, congratulations on self-learning!
Now, to the point.
When you use insert ... values, you can't define a where condition for the table on which you're inserting values. insert statement is only used to insert (When you use insert... select, you can define a where condition on the select, not on the table on which you're about to insert values).
So, there are two ways to do what you want:
Create a unique index on the column that you want to test, and then use insert ignore...
In your code, check if the value is already there, and if it's not, then insert it.
I'll tell you how to work with the first suggestion, because it'll teach you a couple of things. As for suggestion 2, I'll leave that for you as homework ;-)
First, you need to add a unique index to your table. If you want to avoid duplicates on the Name column, then:
alter table companies
add unique index idx_dedup_name(Name);
Check the syntax for ALTER TABLE.
And now, let's say that Companies already has a row with name 'XCorp'. If you try a normal INSERT... VALUES statement here, you'll get an error, because you're trying to add a duplicate value. If you want to avoid that error, you can use something like this:
insert ignore into companies(name) values ('XCorp');
This will execute as a normal insert, but, since you're trying to insert a duplicate value, it will fail, but silently (it wil throw a warning instead of an error).
As for suggestion 2, as I told you, I leave it to you as homework.
Hints:
Count the rows where the name matches a value.
Read the count to a variable in your python program
Test the value... if there's zero entries, then perform the insert.

Check if record exists delete it using mysql

i'm using MySQL and i want to check if a record exists and if it exists delete this record.
i try this but it 's not working for me:
SELECT 'Barcelone' AS City, EXISTS(SELECT 1 FROM mytable WHERE City = 'Barcelone') AS 'exists';
THEN
DELETE FROM mytable
WHERE City = 'Barcelone';
Thank you for your help.
The if statement is only allowed in stored procedures, stored functions, and triggers (in MySQL).
If I understand what you want, just do:
DELETE FROM mytable
WHERE City = 'Barcelone';
There is no reason to check for the existence beforehand. Just delete the row. If none exist, no problem. No errors.
I would recommend an index on mytable(city) for performance reasons. If you want to check if the row exists first, that is fine, but it is unnecessary for the delete.
If you mean MySQL is returning an error message (if that's what you mean by "not working for me"), then that's exactly the behavior we would expect.
That SQL syntax is not valid for MySQL.
If you want to delete rows from a table, issue a DELETE statement, e.g.
DELETE FROM mytable WHERE City = 'Barcelone'
If you want to know how many rows were deleted (if the statement doesn't throw an error), immediately follow the DELETE statement (in the same session) with a query:
SELECT ROW_COUNT()
Or the appropriate function in whatever client library you are using.
If the ROW_COUNT() function returns 0, then there were no rows deleted.
There's really no point (in terms of MySQL) in issuing a SELECT to find out if there are rows to be deleted; the DELETE statement itself will figure it out.
If for some reason your use case requires you to check whether there are rows be be deleted, then just run a separate SELECT:
SELECT COUNT(1) FROM mytable WHERE City = 'Barcelone'

Having various troubles with Insert Into

I have an extension I have made and inside this extension there is an "install.sql" file which contains various inserts.
Some of these inserts do it to tables which MAY exist or not depending on the clients site. What I would like to know is how to do for example something like:
"create table if exists" but for an "Insert Into".
This is an example of what im doing:
INSERT INTO `#__virtuemart_shipmentmethods_en_gb`
(virtuemart_shipmentmethod_id, shipment_name, shipment_desc, slug)
VALUES ((SELECT MAX(vs.virtuemart_shipmentmethod_id)
FROM `#__virtuemart_shipmentmethods` vs), 'Kiala','', 'kiala');
Thanks in advance for your help.
i don't know if i got your question right....
you want to insert somesthing and if its already there you want to update ?
if yes, you propably looking for THIS HERE otherwise your question is set up bad or its to late for me to get it right :)
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
if you don't know if the table exists than you might should check all befor
usual i use pdo, don't know what you use but my solution would be some like this
$result = mysql_query("SHOW TABLES LIKE '#__virtuemart_shipmentmethods_en_gb'");
$tExists = mysql_num_rows($result) > 0;
if(!$tExists)
// Create Table Code here
Have you considered running this is a stored procedure? Something like
CREATE PROCEDURE `testprocdure` ()
BEGIN
IF (SELECT COUNT(*)
FROM information_schema.tables
WHERE table_schema = '[database name]'
AND table_name = '#__virtuemart_shipmentmethods_en_gb') = 1 THEN
INSERT INTO `#__virtuemart_shipmentmethods_en_gb` (virtuemart_shipmentmethod_id, shipment_name, shipment_desc, slug)
VALUES ((SELECT MAX(vs.virtuemart_shipmentmethod_id) FROM `#__virtuemart_shipmentmethods` vs), 'Kiala','', 'kiala');
ELSE
-- Handle if the table doesnt exists
SELECT ''; -- This is just so the SP wont return a error after the else. Remove this when you want to run it
END IF;
END
You could also make use of parameters if you have variable changing.
Then the create syntax should look like this
CREATE PROCEDURE `testprocdure` (IN p_TableName VARCHAR(100))
Change the name of the parameter and datatype to fit your needs.
Could this maybe help?

Multiple MySQL queries (no PHP)

I am wondering if it is possible to perform a SQL query then update another table with the generated ID and continue through all of the rows?
I have this SQL query that works but what I need to do is after each row is added to cards to then update merged.cars_id with the last generated ID so they are linked. normally I would do this with PHP but ideally I would like to just do it with MySQL if possible.
MAIN QUERY
INSERT INTO cards (first_contact_date, card_type, property_id, user_id)
SELECT first_contact_date, 'P', property_id, user_id FROM merged
THEN I NEED WITH MATCHING ROWS (Roughly)
UPDATE merged SET merged.card_id = LAST_INSERT_ID (FROM ABOVE) into the matching record..
Is something like this possible and how do I do it?
I would recommend using MySQL triggers to do this
http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html
A trigger is a function that will be executed AFTER or BEFORE the INSERT or DELETE or UPDATE is done over any record of your table.
In your case you need to do a AFTER INSERT on cards that just updates the merged table. Make sure its AFTER insert as you wont be able to access the new row's ID otherwise.
The code would look something like this, assuming the id field from the cards table its named "id"
delimiter |
CREATE TRIGGER updating_merged AFTER INSERT ON cards
FOR EACH ROW BEGIN
UPDATE merged SET card_id = NEW.id;
END;
|
delimiter ;
May I suggest Stored Procedures?
http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html
--EDIT--
Ah yes, triggers. For this particular situation, Jimmy has the answer. I will leave this post for the sake of the link.
I would set up a trigger to do this. For mysql, read http://dev.mysql.com/doc/refman/5.0/en/triggers.html. This is what triggers are designed to handle.