MySQL INSERT ON DUPLICATE KEY UPDATE ...返回“受影响的行:1”,但实际上没有任何更改

bal*_*d2b 9 mysql insert-update

我创建具有默认值“ 1”的列的表

create table int_1 (
  id int not null auto_increment,
  value int default 1,
  primary key (id)
);
Run Code Online (Sandbox Code Playgroud)

命令

insert into int_1 values(1, null) on duplicate key update value = null;
Run Code Online (Sandbox Code Playgroud)

总是返回结果

1 row(s) affected
Run Code Online (Sandbox Code Playgroud)

但记录在第一次执行后确实发生了更改(插入)。但是,如果我使用默认值“ 0”创建表,则所有功能均按预期工作:

create table int_0 (
  id int not null auto_increment,
  value int default 0,
  primary key (id)
);
insert into int_0 values(1, null) on duplicate key update value = null;
Run Code Online (Sandbox Code Playgroud)

返回

0 row(s) affected
Run Code Online (Sandbox Code Playgroud)

第二次运行后“插入重复键”

在MySQL 5.7,8.0上检查

有这种行为的解释吗?

Ric*_*mes 7

使用ON DUPLICATE KEY UPDATE,如果将行作为新行插入,则每行的受影响行值为1;如果更新了现有行,则为2;如果将现有行设置为其当前值,则为0。如果在连接到mysqld时为mysql_real_connect()C API函数指定CLIENT_FOUND_ROWS标志,则如果将现有行设置为当前值,则受影响的行值为1(而不是0)。

- https://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html

  • 问题是“为什么插入重复键更新总是返回受影响的 1 行,但如果列没有空默认值,则实际上没有行发生更改” (2认同)

小智 1

这是我最近在 MySQL 5.7 中发现的一个有趣的事情。如果您故意尝试使用重复键更新插入已存在的行,则此查询也将复制受影响的行数。

例如,运行以下查询:

CREATE TABLE int_0 (
 id INT NOT NULL AUTO_INCREMENT,
 VALUE INT DEFAULT 0,
 PRIMARY KEY (id) 
);

INSERT INTO int_0 VALUES(1, NULL) ON DUPLICATE KEY UPDATE VALUE = NULL;
Run Code Online (Sandbox Code Playgroud)

然后运行这个:

INSERT INTO int_0 VALUES(1, 2) ON DUPLICATE KEY UPDATE VALUE = 2;
Run Code Online (Sandbox Code Playgroud)

即使表中只有 1 行,此查询也会显示“2 行受影响”,因此影响 2 行是不可能的。

我的理论是,它试图计算受插入和更新影响的行数,然后将它们加在一起。不知何故,ON DUPLICATE KEY UPDATE被触发的行被计为受插入“影响”的行。我相信这就是您所看到的行为。