mysql duplicate key update issue - mysql

I have my index set to the field: testsuite_id and I'm executing the following query:
INSERT INTO testsuite_dates (testsuite_id,start_date,end_date)
VALUES ('27798','2012:02:27 00:00:00','2012:02:28 00:00:00')
ON DUPLICATE KEY UPDATE testsuite_id='27798';
I would expect this to update the entry if an entry for testsuite_id exists or insert it if it doesn't but if I execute this query a second time it inserts a second entry with the same testsuite_id.
What am I missing?

Then you don't have a PRIMARY or UNIQUE key on testsuite_id.

The "on duplicate key update" only changes the fields YOU specify in the 'update' portion. You're updating only the key field, which triggered the constraint violation in the first place. The other fields are silently dropped, so you're effective doing update yourtable set id=id where id=xxx.
You have to list each field you want to be updated:
INSERT INTO testsuite_dates (testsuite_id,start_date,end_date)
VALUES ('27798','2012:02:27 00:00:00','2012:02:28 00:00:00')
ON DUPLICATE KEY UPDATE
start_date=values(start_date), end_date=values(end_date)
Note the use of the values() function in the update portion. This allows you to refer to the NEW value that would've been inserted, and use it for the update portion. This saves you having to embed the same data twice in the same query. Not a big deal for a few dates or numbers, but if you're inserting large blobs, it makes for a HUGE query string size savings.

did you set your testsuite_id to be a primary key, or have unique constraint

INSERT INTO testsuite_dates (testsuite_id,start_date,end_date)
VALUES ('27798','2012:02:27 00:00:00','2012:02:28 00:00:00')
ON DUPLICATE KEY UPDATE testsuite_id=testsuite_id+1;

Related

Ignore values on insert with ON DUPLICATE UPDATE

I have an Insert Statement like:
f"INSERT INTO `system_measurements`(`Global_irradiance_tilted_in_Wh_per_m2`, `a_id`, `subDate`) VALUES ('{temp}', '{temp_id}', '{i.date()}')"
And want it to ignore existing entries without checking the date everytime. So i thouhgt I could use
ON DUPLICATE KEY UPDATE a_id=a_id
But it still adds all values to the table.
I interpret your question as saying that a new row is inserted despite the on duplicate key.
In order for on duplicate key to work, you need a unique constraint or index. The update takes place when the query violates the unique constraint.
I am guessing that you want this on a_id, so be use you have something like:
alter table system_measurements add constraint unq_ system_measurements_a_id
unique (a_id);
INSERT IGNORE will do nothing other than discovering that it is a duplicate. "Duplicate" is checked via the PRIMARY KEY and any UNIQUE keys.
Simply stick IGNORE after INSERT in the SQL you have.

MySQL "Insert ... On Duplicate Key" with more than one unique key

I've been reading up on how to use MySQL insert on duplicate key to see if it will allow me to avoid Selecting a row, checking if it exists, and then either inserting or updating. As I've read the documentation however, there is one area that confuses me. This is what the documentation says:
If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that would cause a duplicate value in a UNIQUE index or PRIMARY KEY, an UPDATE of the old row is performed
The thing is, I don't want to know if this will work for my problem, because the 'condition' I have for not inserting a new one is the existence of a row that has two columns equal to a certain value, not necessarily that the primary key is the same. Right now the syntax I'm imagining is this, but I don't know if it will always insert instead of replace:
INSERT INTO attendance (event_id, user_id, status) VALUES(some_event_number, some_user_id, some_status) ON DUPLICATE KEY UPDATE status=1
The thing is, event_id and user_id aren't primary keys, but if a row in the table 'attendance' already has those columns with those values, I just want to update it. Otherwise I would like to insert it. Is this even possible with ON DUPLICATE? If not, what other method might I use?
The quote includes "a duplicate value in a UNIQUE index". So, your values do not need to be the primary key:
create unique index attendance_eventid_userid on attendance(event_id, user_id);
Presumably, you want to update the existing record because you don't want duplicates. If you want duplicates sometimes, but not for this particular insert, then you will need another method.
If I were you, I would make a primary key out of event_id and user_id. That will make this extremely easy with ON DUPLICATE.
SQLFiddle
create table attendance (
event_id int,
user_id int,
status varchar(100),
primary key(event_id, user_id)
);
Then with ease:
insert into attendance (event_id, user_id, status) values(some_event_number, some_user_id, some_status)
on duplicate key
update status = values(status);
Maybe you can try to write a trigger that checks if the pair (event_id, user_id) exists in the table before inserting, and if it exists just update it.
To the broader question of "Will INSERT ... ON DUPLICATE respect a UK even if the PK changes", the answer is yes: SQLFiddle
In this SQLFiddle I insert a new record, with a new PK id, but its values would violate the UK. It performs the ON DUPLICATE and the original PK id is preserved, but the non-UK ON DUPLICATE KEY UPDATE value changes.

MYSQL: Getting existing primary key when inserting record with duplicate unique key?

I've got a mysql database with a table that has both a auto-increment primary key and unique string valued key (a sha-1 hash).
If I try to add a record that has the same sha-1 hash as an existing record, I just want to get the primary key of the existing record. I can use something like "INSERT ... ON DUPLICATE KEY UPDATE" or "INSERT IGNORE" to prevent an exception when trying to insert a record with a existing hash value.
However, when that happens, I need to retrieve the primary key of the existing record. I can't find a way to do that with a single SQL statement. If it matters, my code is in Java and I'm using JDBC.
Alternatively, I can do it with two statements (either a query followed by an insertion if not found, or a insertion followed by a query if a duplicate key exists). But I presume a single statement would be more efficient.
If I try to add a record that has the same sha-1 hash as an existing
record, I just want to get the primary key of the existing record. I
can use something like "INSERT ... ON DUPLICATE KEY UPDATE" or "INSERT
IGNORE" to prevent an exception when trying to insert a record with a
existing hash value.
If you have an UNIQUE index on a column, no matter what you tried, the RDMS will not allow duplicates in that column (except for the NULL value).
As you said, there is solution to prevent "error" if this appends. Probably INSERT IGNORE in your case.
Anyway, INSERT and UPDATE modify the database. MySQL never return values for these statements. The only way to read your DB is to use a SELECT statement.
Here the "workaround" is simple, since you have an UNIQUE column:
INSERT IGNORE INTO tbl (pk, sha_key) VALUES ( ... ), ( ... );
SELECT pk, sha_key FROM tbl WHERE sha_key IN ( ... );
-- ^^^
-- Here the list of the sha1 keys you *tried* to insert
Actually, INSERT...ON DUPLICATE KEY UPDATE is exactly the right statement to use in your situation. When you use ON DUPLICATE, if the insert happens without duplicate, JDBC returns count of 1 and the ID of the newly inserted row. If the action taken is an update due to duplicate, JDBC returns count of 2 and both the ID of the original row AND the newly generated ID, even though the new ID is never actually inserted into the table.
You can get the correct key by calling PreparedStatement.getGeneratedKeys(). The first key is pretty much always the one you are interested in. For this statement:
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=3;
You can get the inserted or updated ID by calling:
Long key;
ResultSet keys = preparedStatement.getGeneratedKeys();
if (keys.next())
key = keys.getLong("GENERATED_KEY");

Insert ... on duplicate key update nothing using MySQL

My problem is that I have multiple unique keys on a table.
Insert ignore is not an option because it suppresses the errors.
MySQL has no support for any type of conditionals outside a statement (ex. if (cond) then insert else don't insert)
Stored procedures are not an option (the only place I can use the if/else statements)
On duplicate key might update a key with a new value, but I want the unique keys not to change in case one fails the unique constraint.
So the only option would be on duplicate just don't update anything. Is there any way I can achieve this? Or are there any other options?
If you want ON DUPLICATE KEY UPDATE to not actually do anything, just set a column value to the existing value. Other conflicts such as foreign key constraints will bubble up, unlike using the IGNORE keyword, but no values will change on conflict.
INSERT INTO table (value1, value2) VALUES ('1', '2')
ON DUPLICATE KEY UPDATE value1 = value1;
If you want to ensure that no valid data changes in the event of a conflict, you can add a column with arbitrary data in it to the table, and use that for the UPDATE statement.
A third option if you wish to keep all logic in your application and not in the database is to run a SELECT statement first to inspect potential conflicts before running your INSERT/UDPATE statement.
Although ruled out for your scenario, a stored procedure would also be able to provide this logic in a single database call.
Found another option in case someone stumbles across this issue.
If your table has an autoincremented primary key , you can update the pk like this :
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

why the term key in on duplicate statements?

I am new to mysql and was reading about on duplicate key update. The statement we generally write would be something like this
insert into table (col1,col2) values(1,1) on duplicate key update col2=1;
Assuming col1 to be primary.
My understanding of this is statement is that if there is duplicate value in col1 the respective statement updates col2 with 1. My question is why do we use the term "key" in this statement? As it is understood that the statement updates only when there is a primary key violation. Are there any other parameters or function which we can use with duplicate?
Thanks
MySQL updates either if there is a primary or a unique key violation. The manual covers it quite extensively in a separate chapter with examples:
If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that
would cause a duplicate value in a UNIQUE index or PRIMARY KEY, MySQL
performs an UPDATE of the old row.
The term key is used as part of the syntax definition. The term is afaik only available when performing INSERT-statements. If you insert data by any other means (I can only think of LOAD DATA right now), other mechanisms come into place.
There are no other options with this command. In additional I want to say that you can rewrite the statement in this way -
INSERT INTO table (col1, col2) VALUES(1, 1) ON DUPLICATE KEY UPDATE col2 = VALUES(col2);
Also you can use:
an INSERT statement with IGNORE keyword to ignore errors.
a REPLACE statement to replace records by unique key.
In other words INSERT+ON DUPLICATE KEY UPDATE works like an INSERT and REPLACE in one statement. And one more thing - the INSERT+ON DUPLICATE KEY UPDATE statement has big advantage, it does not remove records on updating; the REPLACE statement removes and then inserts new record.