INSERT ... ON DUPLICATE KEY UPDATE - mysql

I am using a API to fetch records from a different server and insert into my local database but when a particular field say apiserverID is duplicate i just want to update fields.
my problem is that i have table structure as
myPrimaryKey
apiserverID
....
.....
.....
updateDate
now i want simple procedure to update the row if apiserverID is duplicate.
Only solution i know is i have to check (SELECT) if the key apiserverID exist then update else insert.
but i don't want do programming for this is this possible in one query
EDIT : Main problem is that INSERT ... ON DUPLICATE KEY UPDATE don't work for a particular field, it include all the keys to check duplicity

if there is a single multiple-column unique index on the table, then the update uses (seems to use) all columns (of the unique index) in the update query.
So if there is a UNIQUE(a,b) constraint on the table in the example, then the INSERT is equivalent to this UPDATE statement:
UPDATE table SET c=c+1 WHERE a=1 AND b=2;
(and not "a=1 OR b=2")
But in your case it will work as expected because first one is your primary key and it will never be duplicate form the server so only thing which can be duplicate is your apiserverID so when ever found duplicate it will update the row else always a new insert will be executed

Related

insert on duplicate key update

I would like to use "insert on duplicate key update" in a query to either insert a new row if it does not exist or update a row if it does. What I can not seem to figure out is how to use this if I do not have the unique id (because the row has not yet been created, and this ID will be autoincremented upon insert)
insert into foodchoices (unique,notunique) values (Idonthavethis,'test')
on duplicate key update notunique = 'stuff';
Now, in this example above, where it says "Idonthavethis", I do not have any unique value for this field, because it has not yet been inserted as a row. However, I do expect that this inserts somehow, I just dont know how. I expect it to act like this:
insert into foodchoices (notunique) values ('test')
BUT, if it is a field that does already exist, I WILL have that unique value. Is there some form of wildcard or something I can use for when I do not have the unique value?
I believe the answer to this is addressed in the MySQL docs:
If a table contains an AUTO_INCREMENT column and INSERT ... UPDATE inserts a row, the LAST_INSERT_ID() function returns the AUTO_INCREMENT value. If the statement updates a row instead, LAST_INSERT_ID() is not meaningful. However, you can work around this by using LAST_INSERT_ID(expr). Suppose that id is the AUTO_INCREMENT column. To make LAST_INSERT_ID() meaningful for updates, insert rows as follows:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
I think what you just might try to do is select the row with the value you have (if exists then update) otherwise insert. It's just one more sentence.
I just don't see how can you compare an existing value that you just don't have (the generated ID). Plus, if the ID is DB seeded how it'll be duplicated?
May be you need to alter your table structure for adding any constraint to "notunique" column. So you can:
insert into foodchoices (notunique) values ('test') on duplicate key update columntostoreyouruniqueid = unique;
if notunique has no constaint then it mean that you will have uniqueid as set. So it has to double query.

Does mySql have an update/insert combo which inserts if the update fails?

I'm not optimistic that this can be done without a stored procedure, but I'm curious if the following is possible.
I want to write a single query insert/update that updates a row if it finds a match and if not inserts into the table with the values it would have been updating.
So... something like
updateInsert into table_a set n = 'foo' where p='bar';
in the event that there is no row where p='bar' it would automatically insert into table_a set n = 'foo';
EDIT:
Based on a couple of comments I see that I need to clarify that n is not a PRIMARY KEY and the table actually needs the freedom to have duplicate rows. I just have a situation where a specific entry needs to be unique... perhaps I'm just mixing metaphors in a bad way and should pull this out into a separate table where this key is unique.
I would enforce this with the table schema - utilize a unique multi-column key on the target table and use INSERT IGNORE INTO - it should throw an error on a duplicate key, but the insert will ignore on error.

Which is a faster way for checking for duplicate entries, then creating a new entry?

I want to check if an entry exist, if it does I'll increment it's count field by 1, if it doesn't I'll create a new entry and have it's count initialize to 1. Simple enough, right? It seems so, however, I've stumbled upon a lot of ways to do this and I'm not sure which way is the fastest.
1) I could use this to check for an existing entry, then depending, either update or create:
if(mysql_num_rows(mysql_query("SELECT userid FROM plus_signup WHERE userid = '$userid'")))
2) Or should I use WHERE_EXISTS?
SELECT DISTINCT store_type FROM stores
WHERE EXISTS (SELECT * FROM cities_stores
WHERE cities_stores.store_type = stores.store_type);
3) Or use this to insert an entry, then if it exists, update it:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
4) Or perhaps I can set the id column as a unique key then just wait to see if there's a duplicate error on entry? Then I could update that entry instead.
I'll have around 1 million entries to search through, the primary key is currently a bigint. All I want to match when searching through the entries is just the bigint id field, no two entries have the same id at the moment and I'd like to keep it that way.
Edit: Oh shoot, I created this in the wrong section. I meant to put it into serverfault.
I believe it's 3.
Set an INDEX or a UNIQUE constraint and then use the syntax of number 3.
It depends which case will happen more often.
If it is more likely that the record does not exists I'd go for an INSERT IGNORE INTO, checking affected rows afterwards; if this is 0 the record already exists, so an UPDATE is issued.
Otherwise I'd go for INSERT INTO ... ON DUPLICATE KEY UPDATE.

Create if an entry if it doesn't exist, otherwise update?

Kinda strange to put it into words that short, heh.
Anyway, what I want is basically to update an entry in a table if it does exist, otherwise to create a new one filling it with the same data.
I know that's easy, but I'm relatively new to MySQL in terms of how much I've used it :P
A lot of developers still execute a query to check if a field is present in a table and then execute an insert or update query according to the result of the first query.
Try using the ON DUPLICATE KEY syntax, this is a lot faster and better then executing 2 queries. More info can be found here
INSERT INTO table (a,b,c) VALUES (4,5,6)
ON DUPLICATE KEY UPDATE c=9;
if you want to keep the same value for c you can do an update with the same value
INSERT INTO table (a,b,c) VALUES (4,5,6)
ON DUPLICATE KEY UPDATE c=6;
the difference between 'replace' and 'on duplicate key':
replace: inserts, or deletes and inserts
on duplicate key: inserts or updates
if your table doesn't have a primary key or unique key, the replace doesn't make any sense.
You can also use the VALUES function to avoid having to specify the actual values twice. E.g. instead of
INSERT INTO table (a,b,c) VALUES (4,5,6) ON DUPLICATE KEY UPDATE c=6;
you can use
INSERT INTO table (a,b,c) VALUES (4,5,6) ON DUPLICATE KEY UPDATE c=VALUES(c);
Where VALUES(c) will evaluate to the value specified prevously (6).
Use 'REPLACE INTO':
REPLACE INTO table SET id = 42, foo = 'bar';
See more in the MySQL documentation
As the others have said, REPLACE is the way to go. Just be careful using it though, since it actually does a DELETE and INSERT on the table. This is fine most of the time, but if you have foreign keys with constraints like ON DELETE CASCADE, it can cause some big problems.
Look up REPLACE in the MySQL manual.
REPLACE works exactly like INSERT,
except that if an old row in the table
has the same value as a new row for a
PRIMARY KEY or a UNIQUE index, the old
row is deleted before the new row is
inserted. See Section 12.2.5, “INSERT
Syntax”.
REPLACE is a MySQL extension to the
SQL standard. It either inserts, or
deletes and inserts. For another MySQL
extension to standard SQL — that
either inserts or updates — see
Section 12.2.5.3, “INSERT ... ON
DUPLICATE KEY UPDATE Syntax”.
If you have the following INSERT query:
INSERT INTO table (id, field1, field2) VALUES (1, 23, 24)
This is the REPLACE query you should run:
REPLACE INTO table (id, field1, field2) VALUES (1, 23, 24)

Is there "UPDATE value IF NO SUCH ROW INSERT yyy" in MySQL?

I want to update a table value on Mysql 5 but if the key does not exist create it.
The way I found to do it is by:
INSERT yyy ON DUPLICATE KEY UPDATE field;
The question is : is the format above less efficient than other ways to do it (As the insert will happen only once and update will happen very often)?
for example:
$result = UPDATE field;
if (num_rows_effected($result)==0) INSERT yyy
Furthermore: Is there a better way to do this in Mysql: for example a kind of:
UPDATE value IF NO SUCH ROW INSERT yyy;
Update: For those who suggested REPLACE, here is an extension to my question:
"Thanks! I need to increase a counter that is already in the table (if it exists). If not create a table row with value 1 for this column. How can I do update with this format (REPLACE)? "
There is a REPLACE also.
INSERT ON DUPLICATE KEY UPDATE will fire UPDATE triggers when it will stumble upon a duplicate key and won't violate FK's in case on UPDATE.
REPLACE will fire DELETE and INSERT triggers, and will violate FK's referencing the row being REPLACE'd.
If you don't have any triggers or FK's, then use INSERT ON DUPLICATE KEY UPDATE, it's most efficient.
You seem to be looking for this query:
INSERT
INTO table (key, counter)
VALUES (#key, 1)
ON DUPLICATE KEY UPDATE
counter = counter + 1
You cannot do this with REPLACE unless you have selected previous value of the counter before running the query.
P. S. REPLACE appeared in MySQL before ON DUPLICATE KEY UPDATE and is being kept only for compatibility. There is no performance increase from using it.
Yes, you can use the 'replace' syntax:
REPLACE INTO table1 (key, col1, col2) values (1, 'val1','val2');
This is a feature specific to MySQL and is not necessarily implemented in other databases.
As for efficiency, my guess is that a straight update will be faster, since MySQL essentially catches the duplicate key error and handles it accordingly. However, unless you are doing large amounts of insert/updates, the performance impact will be fairly small.
Look at the REPLACE command, it meets your requirements.