MySql“INSERT ... ON DUPLICATE KEY UPDATE”仍然插入重复记录。我错过了什么?

时间:2009-10-08 13:46:12

标签: mysql duplicates

我有一个简单的表设置有两列,每列是一个键值。存储在每个字段中的值是varchar(45),表示电子邮件地址和关键字。所收集的信息可能会自行复制,因为它与网站浏览数据收集有关。为避免重复条目,我曾尝试使用INSERT IGNORE,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_emailkey_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);

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

4 个答案:

答案 0 :(得分: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的列中的重复项将是1中的MySQL级错误。

请您运行以下查询:

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

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

看看他们是否还有什么东西?

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

对我而言,您似乎只是出于性能原因选择了复合主键,它应该是一个像这样的索引

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,您仍然需要一个唯一的索引。

对不起,我的回复非常晚,但也许有人会像我一样偶然发现:)