insert on duplicate update get "new" generated id - mysql

I want to insert values,and if it exist "insert .. on duplicate update" will update it but it will not update autoincrement val with new inserted one.I heard that insert on duplicate update has some bug WHICH it always generate new id and if exists it will delete it but I want to get exactly this deleted id.(when I use last_inserted_id it just return last id of updated column which is not new inserted one)I want to update id with new inserted query should act like :insert if exists delete exist one and insert new one(with auto increment).I heard that there are replace into but it is so slow and I want just update id with new inserted id.

With respect, you're playing with fire if you try to carry out fancy update logic with autoincrement columns.
If you need a new autoincrement id in a row when you update it, then just delete the old row and insert the new one like Gordon said.
Under some database workloads that may be slightly slower than using insert on duplicate key update. But unless your table contains at least 100 megarows, or unless you're doing at least 10 of these operations per second all day and all night, the performance difference will be trivial. If you do have that kind of database size or workload, ask your database administrator for advice.
REPLACE = DELETE, then INSERT. IODKU never deletes. Each requires you to specify the columns of some UNIQUE key so that it knows what row to work with. A subtle point: If there are multiple UNIQUE keys, REPLACE may delete multiple rows, then insert only one.
IODKU can get the id (either existing or new) by using ... UPDATE id = LAST_INSERT_ID(id), ....

Related

MySQL update row if not found insert -Preference for update first

I ve already seen some questions regarding this like below
MySQL “good” way to insert a row if not found, or update it if it is found
Now i have a summary table which gets updated with the qty every time say a sale occurs. so out of 1000 sales of an item only first time the insert executes and the rest of the times it would be update. My understanding is in Insert on Duplicate Key Update it tries to insert first and if it fails updates. so all 999 times the insert is not successfull
1) Is there a method to check Update first and if not updated then insert in a single statement?
2) which of the below methods would be desirable considering most of the cases update will be successfull
a) using Insert on Duplicate Key Update
b) Call Update; if no rows affected call insert
Right now i am using the second option(b). performance gain is very important here and also i m testing the first option. ill post the results here once done
INSERT ON DUPLICATE KEY UPDATE is the way to go. It does not perform a full insert or how you put it.
For this statement to work there has to be a primary key or unique key on the table and the corresponding columns have to be involved in the statement.
Before it's decided whether an insert or an update statement has to be done, the said keys are checked. This is usually really fast.
With your "update first" approach you gain nothing, no it gets even worse. The primary key lookup has to be done anyway. In the worst case you wasted time by having to look up the primary key two times. First for the update statement (which may not be necessary), then for the insert statement.

REPLACE versus INSERT in SQL

I am doing the following SQL tutorial: http://sql.learncodethehardway.org/book/ex11.html
and in this exercise the author says in the second paragraph:
In this situation, I want to replace my record with another guy but
keep the unique id. Problem is I'd have to either do a DELETE/INSERT
in a transaction to make it atomic, or I'd need to do a full UPDATE.
Could anyone explain to me what the problem is with doing an UPDATE, and when we might choose REPLACE instead of UPDATE?
The UPDATE code:
UPDATE person SET first_name = "Frank", last_name = "Smith", age = 100
WHERE id = 0;
Here is the REPLACE code:
REPLACE INTO person (id, first_name, last_name, age)
VALUES (0, 'Frank', 'Smith', 100);
EDIT: I guess another question I have is why would you ever do a DELETE/INSERT instead of just an UPDATE as is discussed in the quoted section?
According to the documentation, the difference is:
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.
So what it does:
Try to match the row using one of the available indexes;
If the row doesn't exist already: add a new one;
If the row exists already: delete the existing row and add a new one afterwards.
When might using this become useful over separate insert and update statements?
You can safely call this, and you don't have to worry about existing rows (one statement vs. two);
If you want related data to be removed when inserting / updating, you can use replace: it deletes all related data too);
When triggers need to fire, and you expect an insert (bad reason, okay).
First Replace isn't widely understood in all database engines.
Second replace inserts/updates a record based on the primary key. While with update you can specify more elaborate conditions:
UPDATE person SET first_name = 'old ' + first_name WHERE age > 50
Also UPDATE won't create records.
UPDATE will have no effect if the row does not exist.
Where as the INSERT or REPLACE will insert if the row doesn't exists or replace the values if it does.
Update will change the existing records value in table based on particular condition. So you can change one or many records in single query.
Insert or Replace will insert a new record if records is not present in table else will replace. Replace will only work if and only if you provide the primary key value in the insert or replace query. If you forget to add primary key field value than a new record will created in table.
Case example:-
Update: You have a calculation of wages to be done based on a formula using the column values. In this case you will always use update query as using one single query you can update multiple records.
Insert or Replace: Already mentioned in the link you shared.
How the REPLACE INTO statement works:
AS INSERT:
REPLACE INTO table_name (column1name, column2name, ...)
VALUES (value1, value2, ...);
AS UPDATE:
REPLACE INTO table_name SET column1name = value, column2name = value, ... ;
The REPLACE statement checks whether the intended data record's unique key value already exists in the table before inserting it as a new record or updating it.
The REPLACE INTO statement attempts to insert a new record or modify an existing record. In both cases, it checks whether the unique key of the proposed record already exists in the table. Suppose a value of NO or FALSE is returne. In that case, the REPLACE statement inserts the record similar to the INSERT INTO statement.
Suppose the key value already exists in the table (in other words, a duplicate key). In that case, the REPLACE statement deletes the existing record of data and replaces it with a new record of data. This happens regardless of whether you use the first or the second REPLACE statement syntax.
Once the REPLACE INTO statement is used to insert or modify data, it determines first whether the new data record already exists in the table. It checks if the PRIMARY or the UNIQUE KEY matches one of the existing records.
If there is no matching key, the REPLACE works like a normal INSERT statement. Otherwise, it deletes the existing record and replaces it with the new one. This is considered a sort of modification or update of an existing record. However, it would be best if you were careful here. Suppose you do not specify a value for a column in the SET clause. In that case, the REPLACE statement uses the default value (if a default value has been set). Otherwise, it's set as NULL.

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.

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.