Мне нужно обновить таблицу со следующей структурой:
CREATE TABLE `eav_entity_attribute` (
`entity_attribute_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Entity Attribute Id',
`entity_type_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Entity Type Id',
`attribute_set_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Attribute Set Id',
`attribute_group_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Attribute Group Id',
`attribute_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Attribute Id',
`sort_order` smallint(6) NOT NULL DEFAULT '0' COMMENT 'Sort Order',
PRIMARY KEY (`entity_attribute_id`),
UNIQUE KEY `UNQ_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_SET_ID_ATTRIBUTE_ID` (`attribute_set_id`,`attribute_id`),
UNIQUE KEY `UNQ_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_GROUP_ID_ATTRIBUTE_ID` (`attribute_group_id`,`attribute_id`),
KEY `IDX_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_SET_ID_SORT_ORDER` (`attribute_set_id`,`sort_order`),
KEY `IDX_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_ID` (`attribute_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Eav Entity Attributes'
Над таблицей содержит одну строку:
INSERT INTO `eav_entity_attribute`
(`entity_attribute_id`, `entity_type_id`, `attribute_set_id`, `attribute_group_id`, `attribute_id`, `sort_order`)
VALUES
(32758, 4, 224, 3423, 5171, 12)
У меня запущена автоматическая процедура импорта, которая будет читать внешний источник данных и записывать в эту таблицу.
Этот импорт выполняется несколько раз, и поэтому иногда одни и те же данные импортируются несколько раз. В этом случае процедура просто перезаписывает старые данные с новой, даже если новая идентична старой. Условие, когда одни и те же данные существуют, обрабатывается с предложением ON DUPLICATE KEY UPDATE. Это работает почти отлично, за исключением этой конкретной таблицы.
В этой таблице, когда процедура пытается выполнить UPDATE, я получаю сообщение "Дубликат", которое я не могу объяснить. Я отлаживал код, и это запрос, который терпит неудачу (извлечен из INSERT..ON DUPLICATE KEY):
UPDATE eav_entity_attribute
SET
`attribute_group_id` = 3423
,`attribute_id` = 5171
,`attribute_set_id` = 223
,`entity_type_id` = 4
,`sort_order` = 320
WHERE
(`attribute_group_id` = 3423) AND
(`attribute_id` = 5171)
Ошибка следующая:
Error Code: 1062. Duplicate entry '3423-5171' for key 'UNQ_EAV_ENTITY_ATTRIBUTE_ATTRIBUTE_GROUP_ID_ATTRIBUTE_ID'
Я знаю, что пара 3423-5171 уже существует, но UPDATE заменит эти значения самим собой, а не создаст новую запись. Я очень смущен причиной этой проблемы, любое предложение было бы очень желанным. Спасибо.
Обновление - новое обнаружение
У меня появилось какое-то "вдохновение", и я сделал эксперимент. Я удалил ограничение Unique, в которое включено (attribute_set_id
, attribute_id
) (обратите внимание, что это не тот, который был в ошибке), и я запустил запрос INSERT..ON DUPLICATE. Он отлично работал.
Мина - это гипотеза, но это то, что я думаю: данные, которые я пытаюсь записать в таблицу, сталкиваются с двумя ограничениями:
- UNIQUE (
attribute_set_id
,attribute_id
) - UNIQUE (
attribute_group_id
,attribute_id
)
Ошибка INSERT, предположительно из-за ошибки дублирования, вызванной ограничением first. Это вызывает UPDATE, который использует первое ограничение как неявное предложение WHERE. Мое предположение заключается в том, что в таком случае первое ограничение каким-то образом игнорируется, но UPDATE отключается во втором, что раньше не принималось.
Мне все еще не кажется, что это истинная причина для UPDATE, которая заменяет что-то сама собой, чтобы поднять дублируемую ошибку входа, но она может пролить свет на логику, лежащую за ней.
Второе обновление
Я узнал, что таблица, которую я тестировал, фактически содержит много строк (я забыл отключить отфильтрованное представление) в результате успешного импорта других данных. Однако "дублирующий кандидат" по-прежнему уникален в наборе.
Я подтверждаю, что опубликовано в комментариях, когда таблица содержит только эти строки, работает INSERT..ON DUPLICATE, а также только UPDATE. Теперь мне интересно, почему таблица перепуталась, когда в ней больше данных, поскольку мы все еще говорим о том, что одна уникальная строка обновляется с теми же данными.
Третье обновление - найдена коренная причина
Наконец-то я выяснил причину неудачи UPDATE, теперь я должен выяснить, как мне попасть в такое состояние.
Ключ был моей гипотезой в первом обновлении. Просто у меня есть две очень похожие строки (обратите внимание, что я использую разные значения, когда я начал с чистой базы данных).
row,entity_attribute_id,entity_type_id,attribute_set_id,attribute_group_id,attribute_id,sort_order
1,16919, 4, 120, 1746, 80, 1
2,16649, 4, 119, 1744, 80, 210
Вот что происходит:
- INSERT пытается вставить строку со следующими значениями:
120, 4, 1744, 80, 54
. - Это вызывает "дубликат ключа", так как значения
120, 80
являются дубликатами для полейattribute_set_id, attribute_id
(строка 1). -
Затем MySQL запускает UPDATE, который выглядит следующим образом:
Таблица UPDATE
entity_type_id
= 4 ,attribute_group_id
= 1744 ,sort_order
= 54 ГДЕ (attribute_set_id
= 120) И (attribute_id
= 80) -
На этот раз UPDATE терпит неудачу, потому что значения
1744,80
нарушают ограничение на паруattribute_group_id, attribute_id
, найденную в строке 2.
В заключение
- INSERT терпит неудачу, потому что строка 1 имеет те же значения для ключа
attribute_set_id, attribute_id
. - Ошибка UPDATE, поскольку строка 2 имеет те же значения для ключа
attribute_group_id, attribute_id
.
Решение
Мне нужно будет просмотреть всю процедуру импорта, поскольку, теоретически, ни один из таких дубликатов не возникнет. MySQL выполняет свою работу отлично, это сложная база данных.
Спасибо за все предложения.