【问题标题】:Mysql on duplicate key update with primary key and unique keyMysql关于主键和唯一键的重复键更新
【发布时间】:2015-05-07 16:58:34
【问题描述】:

我有一个带有自动递增主键和唯一键的表:

CREATE TABLE `product` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`canonical_url` varchar(750) CHARACTER SET latin1 NOT NULL,
...
PRIMARY KEY (`id`),
UNIQUE KEY `canonical_url_idx` (`canonical_url`)

如果 canonical_url 已经存在,我会使用 on duplicate key 功能更新记录:

"INSERT INTO product(id, canonical_url, name VALUES(?, ? ?) ON DUPLICATE KEY UPDATE name=VALUES(name), id=LAST_INSERT_ID(id)"

KeyHolder productKeyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(conn -> {
  PreparedStatement ps = conn.prepareStatement(productSql, new String[] {"id"});
  ps.setInt(1, id);
  ps.setString(2, canonicalUrl);
  ps.setString(3, name);
}, productKeyHolder);

final int productId = productKeyHolder.getKey().intValue();

问题是我收到了这个错误:

getKey 方法只应在返回单个键时使用。当前键条目包含多个键:[{GENERATED_KEY=594}, {GENERATED_KEY=595}]

有人知道这是什么原因吗?

【问题讨论】:

  • 仅供参考,我刚刚使用spring-boot-2.0.5.RELEASE遇到了同样的问题

标签: mysql spring-jdbc


【解决方案1】:

我自己也遇到了这个问题。根据这里的文档:

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

使用 ON DUPLICATE KEY UPDATE,如果将行作为新行插入,则每行的受影响行值为 1,如果更新现有行,则为 2

因此,当您的查询执行时,如果插入新记录,则会返回其 ID。如果记录已存在,则更新现有记录。如果因为值都匹配而无需更新,则返回一个 ID,修改的行数为 0。但是,如果更新记录,则返回 ID,修改的行数为 2。密钥持有者假设两行已被修改(即使只有一个已被修改)并且错误地返回 ID 加上下一个顺序 ID(即 ID 加 1)。

为了解决这个问题,我只是在尝试调用 getKey 之前检查了 getKeys 中的计数。如果 getKeys 中有多个值,我不会调用 getKey。

【讨论】:

  • 谢谢!我最终做了类似的事情,但直接使用了 JDBC。就我而言,即使在更新期间,我也想获得 ID。使用 JDBC,即使返回两行,我仍然可以获得 ID,但是 spring 的模板会爆炸:(
猜你喜欢
  • 2014-01-12
  • 2023-02-16
  • 2013-09-07
  • 1970-01-01
  • 2010-10-26
  • 1970-01-01
  • 2019-03-12
  • 2019-07-20
  • 1970-01-01
相关资源
最近更新 更多