UPDATE record if present; else INSERT - mysql

I want to update a record which may or may not be present in a table. If it is not present in the database then it will be inserted.
To prevent from select I am using UPDATE statement first and checking affected_rows > 0 if not then I am inserting this record into the table.
I was wondering if there is a better way to do this?

You could use INSERT ... ON DUPLICATE KEY UPDATE syntax:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
http://dev.mysql.com/doc/refman/4.1/en/insert-on-duplicate.html
The difference between this and REPLACE (Femaref's answer) is that REPLACE will delete the old row and then insert a new row if a key is duplicated, while this will update the existing row.

Use Replace instead of Insert.
http://dev.mysql.com/doc/refman/5.0/en/replace.html

Related

INSERT ... ON DUPLICATE KEY UPDATE how can I tell which records updated and which inserted

In a PHP script I'm using the MySQL INSERT ... ON DUPLICATE KEY UPDATE command to insert/update a number of records in my DB.
Is there anything that MySQL returns to say which records were inserted or updated?
An 'ugly' way would be to do a SELECT before each INSERT and see if the key exists before each INSERT but I'd like to know if MySQL has this function built in.
In case anyone need further info on what I'm trying to do is, to save the record id's to a log.
You will need another SELECT regardless, specifically SELECT ROW_COUNT().
From http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_row-count
For INSERT ... ON DUPLICATE KEY UPDATE statements, the affected-rows value is 1 if the row is inserted as a new row and 2 if an existing row is updated.
No, there is no way to tell which records were inserted and which were updated purely with the means provided by MySQL without additional queries. However, you can add a column to the table where you can keep an indicator that you can use to mark the record as updated instead of inserted, e.g.
INSERT INTO YourTable (Col1, Col2, Updated)
VALUES ("value1", "value2", 0)
ON DUPLICATE KEY UPDATE
Col1 = values(Col1),
Col2 = values(Col2),
Updated = 1

how to give where condtion after on duplication key in trigger

The following code is a trigger I wrote in Navicat for Mysql. The inserting part is working correctly but for update I need to update a specific row quantity based on id. How do I write the where clause in the update sql query.
insert into closingstockt(CLS_BSID,CLS_Qty,CLS_SQty,CLS_CDate)
select BS_ID as CLS_BSID,BS_Qty as CLS_Qty,BSS_Qty as CLS_SQty,curdate()
from barstockt
where CLS_BSID=BS_ID
on duplicate key update CLS_Qty=BS_Qty,CLS_SQty=BSS_Qty
ON DUPLICATE KEY UPDATE will update the row which already exist in the database. For example:
INSERT INTO table (field,field2) VALUES ('data1','data2')
ON DUPLICATE KEY UPDATE lastupdate=NOW()
EDIT: I suggest to use IF()
INSERT ... ON DUPLICATE KEY UPDATE with WHERE?

MySQL insert on duplicate key; delete?

Is there a way of removing record on duplicate key in MySQL?
Say we have a record in the database with the specific primary key and we try to add another one with the same key - ON DUPLICATE KEY UPDATE would simply update the record, but is there an option to remove record if already exists? It is for simple in/out functionality on click of a button.
It's a work-around, but it works:
Create a new column and call it do_delete, or whatever, making it a tiny-int. Then do On Duplicate Key Update do_delete = 1;
Depending on your MySQL version/connection, you can execute multiple queries in the same statement. However, if not, just run a separate query immediately afterwords. Either way, the next query would just be: Delete From [table] Where do_delete = 1;. This way, if its a new entry, it will not delete anything. If it was not a new entry, it will then mark it for deletion then you can delete it.
Use REPLACE INTO:
replace into some_table
select somecolumn from othertable
will either insert new data or if thr same data exist will delete the data and insert the new one
The nearest possible solution for the same is REPLACE statement. Here is the documentation for REPLACE.
A similar question was asked on MySQL Forums and the recommended(and only) answer was to use REPLACE.
to be more clear with mySql:
values can be from same table:
replace into table1 (column1,column2) select (val1,val2) from table1
or
values can be from another table:
replace into table1 (column1,column2) select (val1,val2) from table2
or
values can be from any table with condition:
replace into table1 (column1,column2) select (val1,val2) from table1 where <br>column3=val3 and column4=val4 ...
or
also remember values can be static with table name for namesake:
replace into table1 (column1,column2) select (123,"xyz") from table1
no error will be thrown even if the update results in duplicate entry, as it will be replaced.
(remember) only autoincrement value will be increased;
and
if you have column with data-type "TIMESTAMP" with "on update CURRENT_TIMESTAMP", it will have no effect;
Yes of course there is a solutions in MySQL for your problem.
If you want to delete or skip the new inserting record if there already a duplicate record exists in the key column of the table, you can use IGNORE like this:
insert ignore into mytbl(id,name) values(6,'ron'),(7,'son');
Here id column is primary key in the table mytbl. This will insert multiple values in the table by deleting or skipping the new duplicate records.
Hope this will fulfill your requirement.

UPON DUPLICATE KEY increment multiple columns?

Im running a database log and every day I log on a new row. My Mysql query therefore checks if the day (date (the unique key)) already exists, and if so, it tries to increment all the loggable values of the log-row by one. If the date record doesnt eyist yet, it will create a new row.
My SQL query is:
INSERT INTO `log` (`date`,`hits`,`stale`)
VALUES ('2012-03-06',1,1)
ON DUPLICATE KEY
UPDATE `hits`=`hits`+1,`stale`=`stale`+1
WHERE `date`='2012-03-06';"
All columns have 0 as default value, so if this query runs directly after midnight only 'stale' and 'hits' are set to 1. Otherwise 'stale' and 'hits' are both incremented.
I wish! (it doesn't work).
What am I missing? Which separator other then a comma should I use between 'hits' = 'hits' +1 and 'stale'='stale'+1?
Just get rid of the WHERE clause:
INSERT INTO `log` (`date`,`hits`,`stale`)
VALUES ('2012-03-06',1,1)
ON DUPLICATE KEY
UPDATE `hits`=`hits`+1,`stale`=`stale`+1;
Your separator is correct, but the UPDATE has already found the duplicate row to be able to trigger the ON DUPLICATE KEY, so you don't need to try to select it again using WHERE.
INSERT INTO `log` (`date`,`hits`,`stale`)
VALUES ('2012-03-06',1,1)
ON DUPLICATE KEY
UPDATE `hits`=`hits`+1,`stale`=`stale`+1
Demo here.
You shouldn't have the WHERE clause. ON DUPLICATE KEY UPDATE automatically limits the row it affects to the one that has the existing key.
Remove it and your query should work fine.
If you only want to do the update if some specific expression is true, you can do it with two statements:
INSERT IGNORE INTO x VALUES (.....);
UPDATE x SET ..... WHERE .....;
The INSERT will silently fail if there is a duplicate key.

Which record caused INSERT IGNORE not to insert?

In MySQL, when an INSERT IGNORE does not insert anything, is it possible to get the row that caused INSERT IGNORE to "fail"?
Another and more correct approach is to use LAST_INSERT_ID() in ON DUPLICATE KEY UPDATE
That is to change:
INSERT IGNORE INTO the_table (id) VALUES (1);
To:
INSERT INTO the_table (id) VALUES (1)
ON DUPLICATE KEY UPDATE
id = LAST_INSERT_ID(id);
This wil make no changes to the table, but the following call to LAST_INSERT_ID() will return either the id of the newly inserted item or the last result explicitly passed to the function.
One way you can achieve this is to add a field which you can use as a flag, and then add ON DUPLICATE KEY UPDATE dup = dup+1 (or similar) to your query.