2012-11-22 66 views
16

我需要更新結構如下表:的MySQL 5.5.24 - 上更新重複條目,當沒有真正的重複

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會自己替換這些值,而不是創建一個新條目。我對這個問題的原因很困惑,任何建議都會非常受歡迎。謝謝。

更新 - 新發現

我得到了某種形式的「靈感」的,我做了一個實驗。我刪除了涉及attribute_set_id,attribute_id(注意,這不是錯誤中的那個)的唯一約束,並且我運行了INSERT..ON DUPLICATE查詢。它工作完美。

煤礦是一個猜想,但是這是我的想法:我試圖寫表衝突與兩個約束的數據:

  • UNIQUE(attribute_set_idattribute_id
  • UNIQUE(attribute_group_idattribute_id

插入失敗可能是因爲由第一約束提出的重複錯誤的。這會觸發UPDATE,它使用第一個約束作爲隱式的WHERE子句。我的推測是,在這種情況下,第一個約束被忽略,但是UPDATE在第二個約束之前跳過,而之前沒有涉及。

對我來說,這仍然不是一個有效的UPDATE的原因,它替代了某些東西來引發重複的輸入錯誤,但它可能會揭示它背後的邏輯。

第二次更新

我發現我是對實際測試表中包含很多行(我忘了關閉過濾視圖)從其他數據成功導入產生。然而,「重複候選人」在該集合中仍然是獨一無二的。

我確認在註釋中發佈了什麼,當表只包含那些行,INSERT..ON DUPLICATE的作品以及單獨的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 WHERE (attribute_set_id = 120)和(attribute_id = 80)

  • 這次,UPDATE失敗,因爲值​​違反了對第012行中的對attribute_group_id, attribute_id的限制。

總之

  • 插入失敗,因爲第1行具有關鍵attribute_set_id, attribute_id相同的值。
  • 更新失敗,因爲第2行對於密鑰attribute_group_id, attribute_id具有相同的值。

解決方案

我必須檢討整個導入過程,因爲,從理論上講,沒有這樣的複製品應該出現。 MySQL工作正常,數據庫很複雜。

感謝您的所有建議。

+0

MySQL 5.5.24。我將它添加到標題中。 – Diego

+3

奇怪,在5.5.28中工作。 http://sqlfiddle.com/#!2/81569 –

+1

它工作在5.5。20關於這個問題的疑問;我想這裏桌子的大小很重要。 – raina77ow

回答

2

儘量不要更新INSERT ... ON DUPLICATE KEY UPDATEUPDATE子句中的鍵值。如果具有這些關鍵字值的記錄已經存在,請求MySQL更改關鍵值是很奇怪的,所以MySQL的意外行爲並不令人意外。

+0

使用'在重複密鑰更新'不會導致任何奇怪的行爲,這個問題是由於一系列的情況,現在已經解決了。我正在準備一個完整的答案來記錄它。 – Diego

+0

聽起來像這個答案是非常接近!重複密鑰更新中的密鑰值更新絕對是罪魁禍首。 (我只能猜測,即使在這種情況下,MySQL也會以預期的方式運行) – 2013-02-28 19:46:07