Bug #79937 | Incorrect record updated using ON DUPLICATE KEY UPDATE processing | ||
---|---|---|---|
Submitted: | 12 Jan 2016 15:42 | Modified: | 13 Jan 2016 12:15 |
Reporter: | Katherine Walker | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | MySQL Server: DML | Severity: | S3 (Non-critical) |
Version: | 5.6.27 | OS: | Any |
Assigned to: | CPU Architecture: | Any | |
Tags: | On duplicate key zero primary key |
[12 Jan 2016 15:42]
Katherine Walker
[13 Jan 2016 11:17]
MySQL Verification Team
Hello Katherine, Thank you for the report and test case. Imho this is not a bug and expected behavior. -- 5.6.28 drop table if exists fred; CREATE TABLE fred ( id int(11) NOT NULL, code varchar(32) NOT NULL, stock int(5) NOT NULL, is_active tinyint(1) NOT NULL DEFAULT '1', PRIMARY KEY (id), UNIQUE KEY code (code) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO fred VALUES (0, 'a', 123, 1), (2, 'b', 234, 1), (3, 'c', 345, 1); INSERT INTO fred (code,stock,is_active) VALUES ('b',46,68) ON DUPLICATE KEY UPDATE stock = VALUES(stock), is_active = VALUES(is_active); Imho, Field 'id' doesn't have a default value, and for numeric types, the default is 0(with strict mode, above statement will fail - ERROR 1364 (HY000): Field 'id' doesn't have a default value). So, here id=0, code='b' which matches 2 rows, and at the end only one row is updated. Hence, In general, you should try to avoid using an ON DUPLICATE KEY UPDATE clause on tables with multiple unique indexes. mysql> select * from fred; +----+------+-------+-----------+ | id | code | stock | is_active | +----+------+-------+-----------+ | 0 | a | 46 | 68 | | 2 | b | 234 | 1 | | 3 | c | 345 | 1 | +----+------+-------+-----------+ 3 rows in set (0.00 sec) -- if id is included, and doesn't exists then 'b' that would cause a duplicate value in a UNIQUE index. drop table if exists fred; CREATE TABLE fred ( id int(11) NOT NULL, code varchar(32) NOT NULL, stock int(5) NOT NULL, is_active tinyint(1) NOT NULL DEFAULT '1', PRIMARY KEY (id), UNIQUE KEY code (code) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO fred VALUES (1, 'a', 123, 1), (2, 'b', 234, 1), (3, 'c', 345, 1); INSERT INTO fred (code,stock,is_active) VALUES ('b',46,68) ON DUPLICATE KEY UPDATE stock = VALUES(stock), is_active = VALUES(is_active); mysql> select * from fred; +----+------+-------+-----------+ | id | code | stock | is_active | +----+------+-------+-----------+ | 1 | a | 123 | 1 | | 2 | b | 46 | 68 | | 3 | c | 345 | 1 | +----+------+-------+-----------+ 3 rows in set (0.00 sec) Thanks, Umesh
[13 Jan 2016 12:15]
Katherine Walker
Thank you for your investigation. While I understand your reasoning I struggle to accept that a defaulted value on an INSERT should take priority over a specified value when matching an existing record.