VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
INSERT ... ON DUPLICATE KEY UPDATE writes it if it is not and changes it if it is, in 1 statement and
without a check first. It is the statement behind every “save this setting” and
every counter that has to be created before it can be raised.
These examples use the sakila_practice database from
INSERT. Run the setup block there again before you start,
then open the client with mysql -u root -p sakila_practice.
How it works
TABLE_NAME with the table, COLUMN_LIST and VALUE_LIST with the
columns and values as in an ordinary insert, ROW_ALIAS with a name for the
row you are offering, and COLUMN_NAME with the column to change when the row
is already there.
The ON DUPLICATE KEY UPDATE clause runs only when the insert would break a
PRIMARY KEY or a UNIQUE index. The alias names the row you tried to insert,
so ROW_ALIAS.COLUMN_NAME is the value you offered and the bare column name is
the value already stored.
Examples
1) The collision this avoids
rating_count has rating as its primary key. Write a row.
2) Insert, or update what is in the way
2 rows affected. That count is the
statement’s way of saying which branch it took: 1 for a row inserted, 2 for a
row updated, and 0 when the update found the value already correct.
3) The same statement on a row that is not there
1 row affected is the insert branch. Nothing about the statement changed
except the values, which is the point of it: the caller does not have to know
whether the row is there.
Refreshing a whole summary
The rows can come from a query, which is how a summary table is brought up to date in 1 statement. The alias form is not allowed there.Duplicates: 1 is the G row, which was stored as 179 and is now 178. The 3
new ratings account for 3 of the 5 affected rows and that single update for the
other 2. R already held 195, so it counted nothing at all.
Older code uses VALUES() instead of an alias
Older statements read the offered value withVALUES(films) in place of the
alias. That form still works, and it raises a warning.
\G ends a statement the way a semicolon does and prints 1 column per line,
which is how you read a message too wide for a table. Write new statements with
an alias, and expect to meet VALUES() in code written earlier.
Summary
- Use
INSERT ... ON DUPLICATE KEY UPDATEwhen the row may or may not be there. - Expect the clause to run only on a
PRIMARY KEYorUNIQUEcollision. - Read the affected-row count as 1 for an insert, 2 for an update and 0 for no change.
- Name the offered row with
AS aliasand read its values asalias.column. - Wrap the query in a derived table when the rows come from a
SELECT. - Replace
VALUES(col)with the alias form, which is what warning 1287 asks for.
See also
- INSERT — the plain form and
ERROR 1062 - INSERT SELECT — rows from a query
- UPDATE — changing a row you know is there
- UPSERT in MySQL — REPLACE, INSERT IGNORE and which to reach for

