MySQL在重复密钥更新上使用主密钥和唯一键



我有一个带有自动增量主键的表,也有一个唯一的键:

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`)

im使用ON重复关键功能来更新记录,如果Canonical_url已经存在:

"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}]

有人知道是什么原因引起的?

我自己遇到了这个。根据此处的文档:

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

使用重复的密钥更新,如果将行插入新行,则每行影响行值为1,并且如果更新了现有行,则 2

因此,当查询执行时,如果插入了新记录,则返回ID。如果记录已经存在,则现有记录已更新。如果不需要更新,因为所有值全部匹配,则返回一个ID,并且修改的行数为0。但是,如果记录已更新,则返回ID,并且修改的行数为 2 。关键持有人假设已经修改了两个行(即使仅一行),并且错误地返回ID加上下一个顺序ID(即ID加1)。

为了解决这个问题,我只是在尝试致电GetKey之前检查了GetKeys中的计数。如果GetKeys中有多个值,我不会称呼GetKey。

假设在重复的情况下,临时插入的行将具有更大的ID,以下是:

public static int getGeneratedKeyOnDuplicate(KeyHolder keyHolder)
{
    int id = 0;
    List<Map<String, Object>> keyList = keyHolder.getKeyList();
    if (keyList.size() == 1 && keyHolder.getKey() != null)
        id = keyHolder.getKey().intValue();
    else if (keyList.size() > 1)
    {
        id = keyList.stream()
                .map((Map<String, Object> key) -> ((Number) key.get("GENERATED_KEY")).intValue())
                .min(Comparator.comparing(Integer::valueOf))
                .get();
    }
    return id;
}

,但请意识到keyHolder.getKey()java.math.BigInteger的实例,因此我不确定这将如何使用具有很大价值的id

最新更新