I repeat two main points from the previous answers that I think you should keep:
Do not try to use "when re-updating the key" with its MySQL-only, as txyoji points out.
Prefer select->if not found, then insert->else paste, demonstrated by Uday Sawant.
Here's another point: Concurrency. Although for low-traffic applications, the likelihood that you will have problems is minimal (still never equal to zero), I think we will always be careful about this.
From a transactional point of view, "INSERT .. ON DUPLICATE UPDATE" not equivalent to selecting in your application memory and then inserting or updating. The first is one transaction, and the second is not.
Here's a bad scenario:
- You select your entry using
findByPk() , which returns null - Some other transactions (from some other user request) insert a record with an identifier that you simply could not select
- The next moment you try to insert it again
In this case, you will either get an exception (if you are working with a unique key, as you are here), or duplicated. Duplicating entries is much more difficult (usually nothing seems strange until your users see duplicate entries).
The solution here is to set a strict isolation level, such as "serializable", and then start the transaction.
Here is an example for yii:
Yii::app()->db->createCommand('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE'); $trn = Yii::app()->db->beginTransaction(); try {
You can learn more about isolation levels at least in the following links and see what each isolation level can offer in data integrity in exchange for concurrency
http://technet.microsoft.com/en-us/library/ms173763.aspx
http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html
source share