2012-05-30 90 views
1

我有以下(简化)数据库表,代表锦标赛中的团队。每个团队都属于一个池,并且在该池中有一个排名(第一,第二等)。如何一次更新多行,同时避免唯一密钥的问题?

CREATE TABLE `team` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `pool_id` bigint(20) NOT NULL, 
    `rank` bigint(20) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `pool_id_rank_idx` (`pool_id`,`rank`), 
) 

唯一的关键在于,因为单个池不能有两个具有相同等级的团队。

当团队互相竞争时,他们的等级发生变化,我需要更新他们。我希望能够更新一个查询中的所有等级,但是我无法想出一个办法来做到这一点,有时不会导致“重复输入”错误。以下是导致此问题的一种情况的示例:

两个队(A和B)分别在一个池中排名为1和2。他们打对方,B击败A.现在我需要切换他们的队伍。我使用的查询是这样的:

UPDATE team 
SET rank = CASE id WHEN idA THEN 2 WHEN idB THEN 1 END 
WHERE id IN (idA,idB); 

IDA和美洲开发银行的相应小组的ID

这似乎像它应该很好地工作,但我得到这个错误:

ERROR 1062 (23000): Duplicate entry '1-2' for key 'pool_id_rank_idx' 

我认为这是因为MySQL在每行更改后检查唯一键。

是否有任何方法推迟唯一键检查,直到所有更改完成后?

回答

0

等级是动态值,为什么你添加到唯一的密钥?或者你的意思是两个相似的等级值不可能用于一个池?

更新数据时,会出现两个相似的pool_id,排名对 - 这就是原因。

删除唯一密钥:

ALTER TABLE team DROP INDEX pool_id_rank_idx

+0

我的意思是说,一个池中的两个球队不可能有相同的排名。但队伍可以改变,所以我想同时改变他们。 –

+0

当比赛开始时,每支球队已经拥有等级值!= 0? –

+0

在应用程序级别上控制您的数据并删除您的唯一密钥。 –

-2

理想情况下,你不会真地存储这个排名,因为它可以以另一种方式比较容易计算。

但是,要回答您如何推迟唯一密钥检查的问题,实际上可以使用UPDATE IGNORE语法忽略该错误。尽管如此,请谨慎对待,因为它会将每个错误都转化为警告。

UPDATE IGNORE team 
SET rank = CASE id WHEN idA THEN 2 WHEN idB THEN 1 END 
WHERE id IN (idA,idB); 
+0

您链接到的页面表示“发生重复键冲突的行不会更新。”我认为这意味着我实际上无法使用此解决方案。等级存储在该行的原因在于,计算一个(例如)48队比赛的队伍需要很长时间,每队参加6场比赛。 –

+0

如果添加'IGNORE',查询将不会'UPDATE'任何行。 –

+0

是的,你们是对的,我的错。之前我做过这样的事情,并认为它只是'IGNORE'子句,但回去后,看着我的原始代码,我意识到我也在使用'ON DUPLICATE KEY'。它是一个INSERT而不是UPDATE,因此可能不适用于此。对于那个很抱歉 –

相关问题