由于约束错误,我正在对INSERT... ON DUPLICATE KEY
语句进行疑难解答,但我不可逆转地编辑了相关行,并且我不再收到错误。我确定我编辑了request_path
或target_path
。某些区域已存在的一些值:
store_id | id_path | is_system
6 | category/494 | 1
查询
INSERT INTO `core_url_rewrite` (`store_id`,`category_id`,`product_id`,`id_path`,`request_path`,`target_path`,`is_system`)
VALUES (6, 494, NULL, 'category/494', 'lessons/teacher-s-planning-calendar/n-a', 'catalog/category/view/id/494', 1)
ON DUPLICATE KEY UPDATE
`store_id` = VALUES(`store_id`),
`category_id` = VALUES(`category_id`),
`product_id` = VALUES(`product_id`),
`id_path` = VALUES(`id_path`),
`request_path` = VALUES(`request_path`),
`target_path` = VALUES(`target_path`),
`is_system` = VALUES(`is_system`)
错误是
Integrity constraint violation: 1062 Duplicate entry 'category/494-1-6'
for key 'UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID'
此表上有两个唯一的键。
UNIQUE KEY `UNQ_CORE_URL_REWRITE_REQUEST_PATH_STORE_ID` (`request_path`,`store_id`),
UNIQUE KEY `UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID` (`id_path`,`is_system`,`store_id`)
在行上意外手动更改某些值后,我不再遇到此约束错误。什么会导致我的查询提示该约束错误?
答案 0 :(得分:3)
如果修复第一个唯一性约束(通过更新冲突行而不是插入新行)会导致第二个失败,就会发生这种情况。
例如,假设您的表已经包含以下行:
(6, 494, NULL, 'category/123', 'lessons/teacher-s-planning-calendar/n-a', 'catalog/category/view/id/123', 1),
(6, 494, NULL, 'category/494', 'lessons/foobar/whatever', 'catalog/category/view/id/494', 1);
然后尝试插入新行:
(6, 494, NULL, 'category/494', 'lessons/teacher-s-planning-calendar/n-a', 'catalog/category/view/id/494', 1)
将导致第一个约束失败(因为表中已存在request_path = 'lessons/teacher-s-planning-calendar/n-a'
和store_id = 6
的行),因此ON DUPLICATE KEY UPDATE
子句将导致冲突的行被更新代替。但这会导致它违反第二个约束,因为表格中已经另一个行id_path = 'category/494'
,is_system = 1
和{{1} }。
Here's a simple example on SQLize demonstrating this behavior.
事实上,what really happens就是如果store_id = 6
语句INSERT
违反多个唯一性限制,MySQL会尝试将更新应用于所有冲突的行。对于这样的更新,将所有列设置为固定值,这几乎是保证导致进一步的约束违规,因为它有效地尝试使表中的两个不同的行相同。
如链接文档所述:
通常,您应该尽量避免在具有多个唯一索引的表上使用
ON DUPLICATE KEY UPDATE
子句。
答案 1 :(得分:2)
问:什么会导致我的查询提示该约束错误?
INSERT
操作在第一个唯一键(request_path,store_id)
上遇到重复键错误。该错误被MySQL捕获,然后MySQL执行了相当于
UPDATE core_url_rewrite
SET store_id = ?
, category_id = ?
, product_id = ?
, id_path = ?
, request_path = ?
, target_path = ?
, is_system = ?
WHERE ( request_path = ? AND store_id = ? )
OR ( id_path = ? AND id_system = ? AND store_id = ?)
LIMIT 1
更新操作尝试将 id_path
和 id_system
列(在该行上)设置为值 {{1} 和 'category/494'
。
那是"重复的键" '1'
操作返回了错误。该语句仅捕获由UPDATE
操作引起的重复键错误。
错误消息的这一部分:
INSERT
表示构成表中已存在的唯一键的列中的值。
在错误消息中,破折号字符用作每列值之间的分隔符。一般来说,我们无法区分作为分隔符的短划线和作为值的一部分的短划线;所以我们需要注意解析它。
在这种情况下,索引中有两个短划线字符和三列,因此我们可以选择为每个列分配的值。
如果'category/494-1-6'
抛出了"重复的密钥"错误,我们不会看到它。 MySQL会抓住它,并调用INSERT
动作。导致错误的是UPDATE
操作。
答案 2 :(得分:0)
可能你刚刚解决了你的问题,但是我已经把这个提示留给了像我这样来谷歌的其他人。
当 url_rewrite_id 达到 max unsigned int size 4,294,967,295
时,也会产生此错误如果您不使用自定义重写,最快的解决方案就是截断此表并重新重新索引。
$adapter->insertOnDuplicate($this->getMainTable(), $rewriteData);
看起来像INSERT ... ON DUPLICATE UPDATE(由Magento核心索引器使用)每次运行索引器时都会碰坏这个索引。
答案 3 :(得分:0)
请注意,因为A.Maksymiuk建议达到最大unsigned int大小也是一个原因。
在我们的案例中,我们在ERP集成中手动插入和删除了很多行,因此MySql AUTO_INCREMENT字段的增长速度快于实际记录。
错误报告“重复条目”与以下MySql错误有关:
https://bugs.mysql.com/bug.php?id=80373
https://bugs.mysql.com/bug.php?id=66566
在本例中,我们将url_rewrite_id列的类型更改为BIGINT