Inserting auto increment value on duplicate key? - mysql

This seems like it should be simple, but I couldn't figure out a way to do it. Let's say I have a table with 5,000 rows, each with an ID (primary key) of 1–5000. I am blindly inserting a new value with an existing ID, and it could be something like 2677. What I want to happen is that if the ID already exists, it will use the auto_increment value, in this case 5001. That or the maximum existing value + 1.
Most importantly, I can't use PHP (or anything else other than SQL) to do this, because the output is a query that needs to be directly importable without errors.
I have looked at two similar questions on SO:
Can you use aggregate values within ON DUPLICATE KEY
– the problem here is that they're selecting from an existing table which I can't do.
on duplicate key update with a condition? – the problem here is that I have no information on the table I'm importing to (except the basic structure), and don't know what the maximum value is.

INSERT INTO table (column1,column2) VALUES (1,2) ON DUPLICATE KEY UPDATE id=VALUES(id)
Obviously this requires an id column with AUTO_INCREMENT.
Moreover if you later need to select the inserted id just like if it was a new Insert, you do:
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(VALUES(id));

Related

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.

How to avoid duplicate entries without primary key and unique key?

I want to know whether it is possible to avoid duplicate entries or data without any keys or group by statement
Create Unique key constrait.
ALTER TABLE Comment ADD CONSTRAINT uc_Comment UNIQUE (CommentId, Comment)
In above case Comment duplication will not be done as we are creating the unique combination of COmmentId and Comment.
Hope this helps.
More info : http://www.w3schools.com/sql/sql_unique.asp OR
SQL Server 2005 How Create a Unique Constraint?
If you want to suppress duplicates when querying, use SELECT DISTINCT.
If you want to avoid putting duplicates into a table, just don't insert records that are already there. It doesn't matter whether you have a primary/unique key: those will make the database not allow duplicate records, but it's still up to you to avoid trying to insert duplicates (assuming you want your queries to succeed).
You can use SELECT to find whether a record already exists before trying to insert it. Or, if you want to be fancy, you can insert the new records into a temporary table, use DELETE to remove any that are already present in the real table, then use INSERT ... SELECT to copy the remaining records from the temporary table into the real one.

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.