提问者:小点点

MySql“插入…重复键更新”仍然插入重复记录。 我错过了什么?


我有一个简单的表设置了两列,每列是一个键值。 存储在每个字段中的值是表示电子邮件地址和关键字的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;

虽然我看到了几个与这个问题相近的问题,但我没有看到任何一个能解释为什么会发生这种情况的问题,我想找出我对这种行为不理解的地方。 感谢任何帮助。

作为一个补充,在添加了唯一的键语句之后,我返回并尝试了替换和插入忽略来实现我的目标,这些选项都没有排除重复条目。

此外,添加:唯一索引(user_emailkey_token)似乎也没有帮助。

我将通过一个手动查找程序来进行检查,直到我能找出这个问题为止。 如果我找到答案,我会很高兴更新帖子。

在原来的create table语句下面添加了唯一的索引行-

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

看起来还可以(在源代码步骤中创建表时没有错误),但是在运行on duplicate查询时,我仍然得到了重复项。


共3个答案

匿名用户

两列上都有一个复合主键。

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

这些数据可能出现在表中:

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

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

如果希望每个单独的列都是唯一,请在字段上定义唯一约束:

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

看看他们有没有退货?

匿名用户

primary KEY(user_email,key_token)表示两者的组合将是唯一的,但如果您还希望单个电子邮件和key_token是唯一的,则必须对每列分别使用unique

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

匿名用户

目前的最终解决方案是:查询表,通过user_email获取key_token列表,根据列表条目测试当前key_token,如果找到,不要插入。 不是最优的也不是漂亮的,但它很有效。。。。