【问题标题】:MySql "INSERT … ON DUPLICATE KEY UPDATE" still inserting duplicate records. What am I missing?MySql“INSERT ... ON DUPLICATE KEY UPDATE”仍在插入重复记录。我错过了什么?
【发布时间】:2013-09-05 02:32:28
【问题描述】:

我有一个简单的表,有两列,每一列都是一个键值。每个字段中存储的值是 varchar(45),表示电子邮件地址和关键字。收集的信息可能会重复,因为它与网站浏览数据收集有关。为了避免重复条目,我曾经尝试使用 INSERT IGNORE into,REPLACE into,最后我尝试了以下操作:

insert into <table name> (user_email, key_token) values ('<email>@<this>.com', 'discountsupplies') on duplicate key update user_email='<email>@<this>.com',key_token='discountsupplies';

但我仍然看到重复的记录被插入到表中。 生成表的 SQL:

DROP TABLE IF EXISTS `<database name>`.`<table name>` ;

CREATE  TABLE IF NOT EXISTS `<database name>`.`<table name>` (
  `user_email` VARCHAR(45) NOT NULL ,
  `key_token` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`user_email`, `key_token`) )
ENGINE = InnoDB;

虽然我看到了几个与此问题相近的问题,但我没有看到任何解决为什么会发生这种情况的问题,我想弄清楚我对这种行为的不理解。任何帮助表示赞赏。


作为附录,在添加 UNIQUE KEY 语句后,我返回并尝试了 REPLACE 和 INSERT IGNORE 来实现我的目标,这些选项都没有排除重复条目。

另外添加:UNIQUE INDEX (user_email, key_token) 似乎也没有帮助。

我将通过手动查找例程来执行此检查,直到我弄明白为止。如果我找到答案,我会很乐意更新帖子。


在原始创建表语句下方添加了唯一索引行 -

-- -----------------------------------------------------
-- Table `<db name>`.`<table name>`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `<db name>`.`<table name>` ;

CREATE  TABLE IF NOT EXISTS `<db name>`.`<table name>` (
  `user_email` VARCHAR(45) NOT NULL ,
  `key_token` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`user_email`, `key_token`),
  UNIQUE KEY (user_email),
  UNIQUE KEY (key_token)
  )

ENGINE = InnoDB;

CREATE UNIQUE INDEX ix_<table name>_useremail on `<db name>`.`<table name>`(user_email);
CREATE UNIQUE INDEX ix_<table name>_keytoken on `<db name>`.`<table name>`(key_token);

似乎没问题(在源步骤中创建表时没有错误),但是在运行重复查询时我仍然得到重复。

【问题讨论】:

  • 重复是什么意思?您是否在一列中有两封相同的电子邮件(在该列中定义了UNIQUE)?
  • 你能发布一些你认为重复的数据吗?
  • 这是表中第一个出现的 sn-p '剪切和粘贴'(出于隐私考虑,电子邮件已从原始地址修改),证明了重复。即使第一条记录清楚地在表中,第三条记录也会被添加。 melanies@gmail.com tempurpedic-beds melanies@gmail.com child-safety-gates melanies@gmail.com tempurpedic-beds
  • 你需要创建两个 分开 UNIQUE KEYs: CREATE UNIQUE INDEX ix_mytable_useremail ON mytable (user_email), CREATE UNIQUE INDEX ix_mytable_keytoken ON mytable (key_token)

标签: mysql duplicates


【解决方案1】:

两列都有一个复合主键。

这意味着它的字段组合是UNIQUE,而不是每个字段都是这样。

这些数据可能在表格中:

1@example.com  1
2@example.com  1
2@example.com  2

,因为(user_email, key_token) 的组合不会在表中重复,而user_emailkey_token 本身可以重复。

如果您希望每个单独的列都为 UNIQUE,请在字段上定义 UNIQUE 约束:

CREATE  TABLE IF NOT EXISTS `<database name>`.`<table name>` (
  `user_email` VARCHAR(45) NOT NULL ,
  `key_token` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`user_email`, `key_token`),
  UNIQUE KEY (user_email),
  UNIQUE KEY (key_token)
)
ENGINE = InnoDB;

更新

在标记为UNIQUE 的列中有重复项将是MySQL 中的1 级别错误。

您能否运行以下查询:

SELECT  user_email
FROM    mytable
GROUP BY
        user_email
HAVING  COUNT(*) > 1

SELECT  key_token
FROM    mytable
GROUP BY
        key_token
HAVING  COUNT(*) > 1

看看他们有没有回报?

【讨论】:

  • 感谢您的帮助。我只是尝试添加 UNIQUE KEY () 语句并重置测试数据库来尝试这个。恐怕我仍然会重复。就我想要在表格中使用我拥有的数据实现的目标而言,您上面的示例是正确的。
  • 尝试了两个查询 - 我确实得到了两个查询的值,但我没有得到表中的所有电子邮件地址,也没有得到所有关键字 - 只是每个。
  • 您没有创建两个单独的UNIQUE KEYs,而是创建了一个复合的。发出这个:CREATE UNIQUE INDEX ix_mytable_useremail ON mytable (user_email)
【解决方案2】:

PRIMARY KEY (user_email,key_token) 表示两者的组合将是唯一的,但如果您还希望单个电子邮件和 key_tokens 是唯一的,则必须为每列单独使用 UNIQUE..

PRIMARY KEY ('user_email', 'key_token'),
  UNIQUE KEY (user_email),
  UNIQUE KEY (key_token)

【讨论】:

    【解决方案3】:

    目前的最终解决方案:查询表以通过 user_email 获取 key_tokens 列表,针对列表条目测试当前 key_token,如果找到不插入。 不是最佳的或漂亮的,但它有效....

    【讨论】:

    • Quassnoi 提供了很多帮助 - 如果我的桌子按照我的设想正常工作,我会选择他的一个答案作为最终解决方案。这是我最终使用的,所以我选择它作为非最佳但有效的解决方案。
    【解决方案4】:

    在我看来,您选择复合主键只是出于性能原因,它应该是这样的索引

    CREATE  TABLE IF NOT EXISTS `<database name>`.`<table name>` (
      `user_email` VARCHAR(45) NOT NULL ,
      `key_token` VARCHAR(45) NOT NULL,
      PRIMARY KEY (`user_email`),
      INDEX (`user_email`, `key_token`) 
    )
    

    当然,如果您担心得到重复的 key_token,您仍然需要唯一索引。

    对不起,我回复得太晚了,但也许有人会像我一样偶然发现这个:)

    【讨论】:

      猜你喜欢
      • 2018-05-19
      • 2014-06-05
      • 2015-07-30
      • 1970-01-01
      • 2010-11-26
      • 2011-08-09
      • 1970-01-01
      • 2023-02-06
      • 1970-01-01
      相关资源
      最近更新 更多