INSERT INTO tb (name, date, stat1, stat2, stat3)
VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE stat1 = stat1 + VALUES(stat1), stat2 = stat2 + VALUES(stat2), stat3 = stat3 + VALUES(stat3)
Answer from vearutop on Stack OverflowINSERT INTO tb (name, date, stat1, stat2, stat3)
VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE stat1 = stat1 + VALUES(stat1), stat2 = stat2 + VALUES(stat2), stat3 = stat3 + VALUES(stat3)
Add a computed column (sum) and include that in your PK.
However, this does denormalize your table. You could use a surrogate key and do the calculation in your SELECT
php - On Duplicate Key Update - Multiple Columns - Stack Overflow
MySQL behavior of ON DUPLICATE KEY UPDATE for multiple UNIQUE fields - Stack Overflow
mysql - "ON DUPLICATE KEY UPDATE" is not working for multiple columns - Stack Overflow
sql - MySQL ON DUPLICATE KEY UPDATE for multiple rows insert in single query - Stack Overflow
Well, this is old. But of course you only need to provide a value once, there's no reason to add it a second time in the query (which comes in handy for multiple inserts, or prepared statements):
INSERT INTO table1
(col1, col2, col3, col4)
VALUES
('val1', 'val2', 'val3', 'val4')
ON DUPLICATE KEY UPDATE
col2=VALUES(col2),
col3=VALUES(col3) [,...]
Which has as advantage it will still work for a multiple insert statement:
INSERT INTO table1
(col1, col2, col3, col4)
VALUES
('val1', 'val2', 'val3', 'val4'),
('val5', 'val6', 'val7', 'val8'),
('val9', 'val10', 'val11', 'val12')
ON DUPLICATE KEY UPDATE
col2=VALUES(col2),
col3=VALUES(col3) [,...]
A modern PHP example:
$sql = "INSERT INTO table1 (col1, col2, col3, col4) VALUES (?,?,?,?)
ON DUPLICATE KEY UPDATE
col2=VALUES(col2),
col3=VALUES(col3),
col4=VALUES(col4)";
$db->prepare($sql)->execute([$val1, $val2, $val3, $val4]);
INSERT INTO table1
(`col1`, `col2`, `col3`, `col4`)
VALUES
('val1', 'val2', 'val3', 'val4')
ON DUPLICATE KEY UPDATE
`col2`='val2',
`col3`='val3', [...]
I fixed your quotes and tickmarks.
Consider
INSERT INTO table (a,b,c) VALUES (1,2,3)
-> ON DUPLICATE KEY UPDATE c=c+1;
If a and b are UNIQUE fields, UPDATE occurs on a = 1 OR b = 2. Also when condition a = 1 OR b = 2 is met by two or more entries, update is done only once.
Ex here table table with Id and Name UNIQUE fields
Id Name Value
1 P 2
2 C 3
3 D 29
4 A 6
If query is
INSERT INTO table (Id, Name, Value)
VALUES (1, C, 7);
then we get
Id Name Value
1 P 2
2 C 3
3 D 29
4 A 6
1 C 7
which violates uniqueness of Id and Name. Now with
INSERT INTO table (Id, Name, Value)
VALUES (1, C, 7)
ON DUPLICATE KEY UPDATE Value = 7;
we get
Id Name Value
1 P 7
2 C 7
3 D 29
4 A 6
Behavior on multiple keys is the following
UPDATE in ON DUPLICATE KEY UPDATE is performed if one of the UNIQUE field equals the value to be inserted. Here, UPDATE is performed on Id = 1 OR Name = C. It is equivalent to
UPDATE table
SET Value = 7
WHERE Id = 1 OR Name = C;
What if I want one update only, for either key
Can use UPDATE statement with LIMIT keyword
UPDATE table
SET Value = 7
WHERE Id = 1 OR Name = C
LIMIT 1;
which will give
Id Name Value
1 P 7
2 C 3
3 D 29
4 A 6
What if I want one update only if values for both keys are matched
One solution is to ALTER TABLE and make the PRIMARY KEY (or uniqueness) work on both fields.
ALTER TABLE table
DROP PRIMARY KEY,
ADD PRIMARY KEY (Id, Name);
Now, on
INSERT INTO table (Id, Name, Value)
VALUES (1, C, 7)
ON DUPLICATE KEY UPDATE Value = 7;
we get
Id Name Value
1 P 2
2 C 3
3 D 29
4 A 6
1 C 7
since no duplicate (on both keys) is found.
how does MySQL behave ... It behaves as expected, that is executes ON DUPLICATE KEY clause.
Can I have one update for either... In reality, you have only one ON DUPLICATE KEY clause, so you need to put some code to differentiate which constraint was involved. Fortunatelly, it is possible. The only thing you should know, the order of assignment matters, and you can assign multiple times. Suppose, you have unique constraint on a and b, and you want to update c only if a uniqueness is involved: ... KEY UPDATE c = IF(a = VALUES(a) and b <> VALUES(b), VALUES(c), c), b = VALUES(b)
but if you change the order of assignments the second condition within if will be always false.
See 2.
Beginning with MySQL 8.0.19 you can use an alias for that row (see reference).
INSERT INTO beautiful (name, age)
VALUES
('Helen', 24),
('Katrina', 21),
('Samia', 22),
('Hui Ling', 25),
('Yumie', 29)
AS new
ON DUPLICATE KEY UPDATE
age = new.age
...
For earlier versions use the keyword VALUES (see reference, deprecated with MySQL 8.0.20).
INSERT INTO beautiful (name, age)
VALUES
('Helen', 24),
('Katrina', 21),
('Samia', 22),
('Hui Ling', 25),
('Yumie', 29)
ON DUPLICATE KEY UPDATE
age = VALUES(age),
...
I was looking for the same behavior using jdbi's BindBeanList and found the syntax is exactly the same as Peter Lang's answer above. In case anybody is running into this question, here's my code:
@SqlUpdate("INSERT INTO table_one (col_one, col_two) VALUES <beans> ON DUPLICATE KEY UPDATE col_one=VALUES(col_one), col_two=VALUES(col_two)")
void insertBeans(@BindBeanList(value = "beans", propertyNames = {"colOne", "colTwo"}) List<Beans> beans);
One key detail to note is that the propertyName you specify within @BindBeanList annotation is not same as the column name you pass into the VALUES() call on update.