MySql "INSERT ... ON DUPLICATE KEY UPDATE" все еще вставляет дублирующиеся записи. Что мне не хватает? - PullRequest
1 голос
/ 08 октября 2009

У меня есть простая таблица с двумя столбцами, каждый столбец является ключевым значением. в каждом поле хранятся значения varchar (45), представляющие адрес электронной почты и ключевое слово. Вполне возможно, что собранная информация может дублировать себя, поскольку она связана со сбором данных о просмотре сайта. Чтобы избежать повторяющихся записей, я пытался использовать INSERT IGNORE в, REPLACE в, и, наконец, я пытаюсь сделать следующее:

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 для достижения моей цели, и ни один из этих вариантов не исключает повторяющихся записей.

Также добавлено: УНИКАЛЬНЫЙ ИНДЕКС (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);

кажется, что все в порядке (нет ошибок при создании таблиц на этапе исходного кода), но я все еще получаю дубликаты при выполнении запроса на дубликаты.

Ответы [ 4 ]

1 голос
/ 08 октября 2009

У вас есть составной первичный ключ в обоих столбцах.

Это означает, что комбинация полей равна UNIQUE, а не каждому полю, как есть.

Данные приведены в таблице:

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

, поскольку ни одна комбинация (user_email, key_token) не повторяется в таблице, в то время как user_email и key_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

и посмотреть, возвращают ли они что-нибудь?

0 голосов
/ 06 июня 2012

Мне кажется, что вы выбрали составной первичный ключ исключительно из соображений производительности, где он должен быть таким индексом, как

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, вам все равно понадобится уникальный индекс.

Извините, я ужасно опоздал с ответом, но, возможно, кто-то наткнется на это, как у меня:)

0 голосов
/ 08 октября 2009

окончательное решение на данный момент: таблица запросов для получения списка key_tokens по user_email, проверка текущего key_token с записями списка, если найдены, не вставлять Не оптимально или симпатично, но работает ....

0 голосов
/ 08 октября 2009

PRIMARY KEY (user_email,key_token) означает, что комбинация обоих будет уникальной, но если вы также хотите, чтобы отдельные электронные письма и key_tokens были уникальными, вы должны использовать UNIQUE отдельно для каждого столбца.

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