【问题标题】:MySQL Insert / On duplicate key failureMySQL插入/重复键失败
【发布时间】:2015-10-08 16:58:55
【问题描述】:

我有一些代码试图用 2 列的新值更新表的现有行。该行将始终存在。它有一个主键和另一个唯一字段,更新指定唯一字段。我正在使用 INSERT / ON DUPLICATE KEY UPDATE 执行此操作。

但是,这并没有更新行,而是更新了恰好存在主键为 0 的行。如果不存在主键为 0 的行,则它可以正常工作。

我认为发生的事情是因为我没有指定主键 MySQL 在某处为此选择值 0,然后它使用主键 0 更新行而不是我指定唯一索引的实际行.

我确实注意到手册页说:-

一般来说,您应该尽量避免对具有多个唯一索引的表使用 ON DUPLICATE KEY UPDATE 子句。

问题可以证明如下:-

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

使用此数据,以下插入应更新第二行(主键 2,b 代码上的唯一索引),而是使用主键为零和唯一的a 代码的索引。

INSERT  INTO fred (code,stock,is_active) VALUES ('b',46,68) ON DUPLICATE KEY UPDATE stock = VALUES(stock), is_active = VALUES(is_active);

没有切换到为此指定主键(或者只是删除主键为 0 的记录),而不是唯一键,我不知道如何彻底解决这个问题。

【问题讨论】:

  • 你的id不应该有AUTO_INCREMENT吗?
  • 我无法重现您的问题:sqlfiddle.com/#!9/b7d37d/1/0
  • id 不应该有自动增量(本质上 id 和代码是从外部系统生成的 - 代码对某些区域有意义,而 id 用于有效地连接表)。使用自动增量会停止使用 0 的 id,并且没有 0 的 id 不会发生问题。
  • @lad2025 - 删除自动增量后问题很明显 - sqlfiddle.com/#!9/90e4a/1
  • 为什么id不是你自己的主键(自动递增),你添加foreign_id键,它可以是任何值,它对应于外部系统给你的数字,沿着code?

标签: mysql


【解决方案1】:

这是您想要做的工作版本:

CREATE TABLE fred (
   id int(11) NOT NULL,
   `code` varchar(32) NOT NULL,
   stock int(5) NOT NULL,
   is_active tinyint(1) NOT NULL,
   PRIMARY KEY (`code`),
   UNIQUE KEY `code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


INSERT INTO fred (id, code, stock, is_active) VALUES
(1, 'a', 123, 1),
(2, 'b', 234, 1),
(3, 'c', 345, 1);

那么更新你也需要发送ID,但是主唯一键是code。

INSERT  INTO fred (id, code, stock, is_active) VALUES (98, 'b',46,68) ON DUPLICATE KEY UPDATE stock = VALUES(stock), is_active = VALUES(is_active), id = VALUES(id);

【讨论】:

  • 不幸的是,它使用的是 AUTO_INCREMENT,在这种情况下这不是一个选项(它不是 MySQL 自动生成的字段 - 该数字是由外部系统分配的唯一整数)。
  • 应该没问题。即使该字段是 AI,您仍然可以强制 Id
  • 很遗憾没有 - sqlfiddle.com/#!9/cde13 。将0插入到自动增量ID字段,但选择时,它将显示它使用的ID为1。 span>
  • 好的,我现在已经更新了我的答案。这似乎对我有用!
  • 问题在于它需要两个密钥(这两个密钥可能可用也可能不可用 - 并引入了两个密钥之间不匹配的可能性,然后随机选择其中一个进行更新),并且此代码用于各个地方。两者都确实需要设置为唯一键(原因是整数 id 用于提高其他表的负载效率,但在外部分配以应对未来重建数据库的担忧 - 我怀疑这会不会必需)。
猜你喜欢
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多