I have a table that I'm inserting records into. It has a primary key made out of two fields. My syntax up until now has been a simple:
INSERT into table (field,field,field) VALUES ('foo', 'bar', foo') type deal, but I've come across the scenario where I may need to overwrite existing values.
I am familiar, and in the past, have used the INSERT INTO .... ON DUPLICATE KEY UPDATE... syntax, but I recently came across the much more simple REPLACE INTO... syntax.
My assumption of this REPLACE INTO is that IF no data exists for the primary key I'm writing to, it will act as an INSERT. IF the primary does exist however, it will delete the record and insert a new one. Is this correct?
If this is correct, are there any downsides to me just forgoing the INSERT INTO... statement and running a REPLACE INTO... for 100% of the lines users are inserting into the table? Are there any potential risks to using the REPLACE INTO... 100% of the time?
REPLACE does a DELETE first, so if you use foreign key constraints with ON DELETE CASCADE, you could unintentionally delete a lot of dependent data. The re-insert step of REPLACE will not recover that data deleted from dependent tables.
I think I've seen cases where REPLACE causes a new auto-increment value to be generated for the primary key. Maybe if the conflict is based on a secondary UNIQUE KEY instead of the primary key, That could throw off other references to the row even if you don't use foreign key constraints.
Related
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.
I am learning MySQL and used the ON DUPLICATE KEY UPDATE, what this does, if I am not mistaken, when it found a duplicate; it will update the row. So, to my question, is there something like ON DUPLICATE KEY INSERT? like when it found a duplicate, it will still insert the data into the table?
No, there is no way to insert a row that has duplicate values in columns that are constrained against duplicate values. If you could, the result would be that the database would be in a state that violates its own constraints.
You would have to drop any unique key or primary key constraints on the table to allow duplicates in the respective columns.
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");
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;
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.