Have you ever wanted to write a single query that would update fields in a table – but you can’t be 100% sure the record exists yet for you to update? For example, you might have a table that holds configuration data for your application. There will be one record for each user in your system. You could use their “UserID” as the primary key (that is crucial to making this work).
Well, instead of doing this:
<?php
$sql = "SELECT COUNT(UserID) FROM configuration WHERE UserID='SomeUser'";
$result = mysqli_query($db,$sql);
if ($result && mysqli_num_rows($result)>0) {
$aResult = mysqli_fetch_array($result);
$iRecordExists = ($aResult[0]>0?1:0);
}
if ($iRecordExists>0) {
//do an update
$sql = "UPDATE configuration SET someField='someValue' WHERE UserID='SomeUser'";
mysqli_query($db,$sql);
}
else {
//do an insert
$sql = "INSERT INTO configuration SET someField='someValue', UserID='SomeUser'";
mysqli_query($db,$sql);
}
?>
You could just do this:
<?php //insert the user's configuration field - if the record already exists - update instead $sql = "INSERT INTO configuration SET UserID='SomeUser', someField='someValue' ON DUPLICATE KEY UPDATE someField='someValue' "; mysqli_query($db,$sql); ?>
Simply put, the query will attempt to insert the configuration record first. If it finds that the specified UserID already has a configuration record in the table, it will simply update the existing record according to the values you include after “ON DUPLICATE KEY UPDATE”. You can include more than one field to update as well.
[Update: As Paul questioned in the comment below, the WHERE clause is not correct (in my original post). The trick is, you have to include the primary key as part of the insert statement - such as UserID in the example above.]
Is the use of the WHERE clause legal with ON DUPLICATE KEY? (NEW TO THIS)
Hi Brian,
One thing that’s been puzzling me using ON DUPLICATE KEY
as I mentioned above – still learning and would really appreciate some advice
Using ON DUPLICATE KEY requires you create a record with a unique field value – and I would have thought an AUTOINC ID field would suffice, but (as far as I can tell) it doesn’t work.
Using just a primary key autoinc ON DUPLICATE KEY always inserts a new record rather than updating/inserting
I’ve manage to create a unique value (luckily my data has a unique value combination (CONCAT) each time its created)
Q: Can you make ON DUPLICATE key work with just an Autoincrement Primary Key ID?
Paul – I’m not sure why you would use this approach if you have an auto-incrementing pK. If you don’t know the pK and it is an autoinc value, then you are correct, it will always create a new record because you haven’t included a key for comparison in the first part of the statement (ie. INSERT INTO primaryKey=XX, field=YY ). Can you provide an example of the statement you’re using?
Hi Brian,
Firstly – sorry for confusion – was getting my head around ON DUPLICATE KEY for the first time
(I originally thought the AutoInc ID WAS a possible unique key – appreciate your feedback – its good when the penny finally drops)
You have to generate a unique key on insert (and that’s not an AutoInc Field)
My example was on a Link table. Questions – Responses (fixed list) – Sources(people)
The Questions , Responses and Sources all have unique ID’s
BUT I couldn’t see how to make any of THESE unique fields, as the same questions, responses and sources occur more than once in the link table.
BUT – a combination of Question AND Source ID was unique
ie a particular Source has either responded to a Question – in which case update
or has not – in which case insert
my Link table now had a new field to hold a unique response (uni_rsp)
uni_rsp was made UNIQUE and was fed the id of the question and the source
uni_rsp=CONCAT(fk_id_qst_rsp,fk_id_src_rsp)
I guess (correct me if I’m wrong) I could have inserted that into the primary key and not used autoinc
atb
Paul
but at least this was I kept the AtoInc as a clean easy to use value
sorry split last sentence….amend
I guess (correct me if I’m wrong) I could have inserted that into the primary key and not used autoinc, but at least this WAY I kept the AtoInc as a clean easy to use value/index