16

次の構造のテーブルを更新する必要があります。

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'

上記の表には、次の 1 つの行が含まれています。

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 はこれらの値をそれ自体で置き換え、新しいエントリを作成しません。この問題の原因についてはかなり混乱しています。どんな提案でも大歓迎です。ありがとう。

更新 - 新しい発見

ある種の「インスピレーション」を得て、実験を行いました。on ( attribute_set_id, attribute_id)を含む Unique 制約を削除し(注、これはエラーに含まれるものではありません)、INSERT..ON DUPLICATE クエリを実行しました。それは完璧に機能しました。

私は推測ですが、これは私が思うことです: テーブルに書き込もうとしているデータは、2 つの制約と衝突します:

  • ユニーク( attribute_set_id, attribute_id)
  • ユニーク( attribute_group_id, attribute_id)

おそらく、最初の制約によって発生した重複エラーが原因で、INSERT が失敗します。これにより、最初の制約を暗黙の WHERE 句として使用する UPDATE がトリガーされます。私の推測では、そのような場合、最初の制約はどういうわけか無視されますが、UPDATE は 2 番目の制約にトリップします。

これは、何かをそれ自体に置き換えて重複エントリエラーを発生させる UPDATE の正当な理由にはまだ思えませんが、その背後にあるロジックに光を当てる可能性があります。

2 回目の更新

私がテストしていたテーブルには、他のデータのインポートが成功した結果、実際には多くの行が含まれていることがわかりました (フィルター ビューを無効にするのを忘れていました)。ただし、「重複候補」は依然としてセット内で一意です。

コメントに投稿された内容を確認します。テーブルにその行のみが含まれている場合、INSERT..ON DUPLICATE と UPDATE だけが機能します。同じデータで更新される単一の一意の行についてまだ話しているので、テーブルにさらにデータがあるとテーブルがめちゃくちゃになるのはなぜだろうと思っています。

3 回目の更新 - 根本原因を発見

UPDATE が失敗する理由がようやくわかりました。今度は、どうすればそのような状態になるかを調べなければなりません。

手がかりは、最初の更新での私の推測でした。簡単に言えば、2 つの非常によく似た行があります (クリーンなデータベースから開始したため、異なる値を使用していることに注意してください)。

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) AND ( attribute_id= 80)

  • 今回は、行 21744,80にあるペアの制約に値が違反しているため、UPDATE は失敗します。attribute_group_id, attribute_id

要約すれば

  • 行 1 のキーの値が同じであるため、INSERT は失敗しますattribute_set_id, attribute_id
  • 行 2 のキーの値が同じであるため、UPDATE は失敗しますattribute_group_id, attribute_id

解決

理論的には、そのような重複は発生しないはずなので、インポート手順全体を確認する必要があります。MySQL はうまく機能していますが、複雑なのはデータベースです。

すべての提案をありがとう。

4

1 に答える 1

2

UPDATEの句内のキー値を更新しないようにしてくださいINSERT ... ON DUPLICATE KEY UPDATE。これらのキー値を持つレコードがすでに存在する場合、MySQLにキー値を変更するように依頼するのは奇妙です。したがって、MySQLの予期しない動作は驚くべきことではありません。

于 2012-12-13T09:52:18.830 に答える