2012-11-20 167 views
7

我有一张表,其中包含商店ID和玩家ID以及玩家的积分。 我想要做的是将一个商店转移到另一个商店,事情是商店id和玩家id形成一个独特的索引。我想要做的是重复键更新,而不是让它失败,将一个条目的点添加到另一个条目并删除“from”条目。 喜欢的东西:更新重复密钥更新

UPDATE `playerspoints` 
SET `boardId`=$to 
WHERE `boardId`=$from 
ON DUPLICATE KEY UPDATE `points`=.... get the idea? 
+0

我的猜测是,2(ish)查询和if/else块会更简单。你有没有想要这样做的特殊原因? – landons

+2

充分利用语言的潜力是一种很好的做法。它更多的是发现事物,并以更快的方式做事。 –

+0

如果将它部署到生产中,我真的希望这有[正确的SQL转义](http://bobby-tables.com/)。看到像这样的裸体变数令人担忧。 – tadman

回答

3

你只能改变一个冲突行中ON DUPLICATE KEY区域的上下文。此外,据我所知,这是INSERT声明的一个属性。

您需要的是一个简单的总账,您可以记录余额的加减,然后将其手动或使用触发器列表。

例如,最简单的方法是:

INSERT INTO points_adjustments (boardId_from, boardId_to, points) 
    VALUES (?, ?, ?) 

这可能更容易表现为一对条目:

INSERT INTO points_adjustments (boardId, points) 
    VALUES (?, ?) 

你会添加一个条目+ n个点,并一个匹配的-n。您随时可以使用SUM(points)获得余额。您可以将其包装在VIEW中以使检索更容易,或者如果需要,可以使用触发器将这些总和非规格化为另一个表的列。

一个简单的触发器会发出为每个受影响boardId下面的语句:

INSERT INTO balances (boardId, points) VALUES (?, ?) 
    ON DUPLICATE KEY SET points=points+VALUES(points) 

这样就避免了在首位键冲突,并提供发生的交易的审计记录。

在任何情况下,要自动完成所有这些,您可能必须使用触发器。

+0

我喜欢这个解决方案,但我从来没有使用触发器,我猜这是我的时间。 至于逃避... $ from \t =(int)mysql_real_escape_string($ _ REQUEST ['from']); \t \t \t \t $ to \t =(int)mysql_real_escape_string($ _ REQUEST ['to']); \t \t \t \t $ delete = $ condition [mysql_real_escape_string($ _ REQUEST ['delete'])]; \t \t \t \t $ contest = $ condition [mysql_real_escape_string($ _ REQUEST ['contest'])]; 还有什么我可以做的吗? –

+0

是的。触发器将是合乎逻辑的下一步。自动删除约束违规是一个雄心勃勃的想法:) – landons

+0

是......使用PDO(或其他数据库抽象库)。 – landons

0

不可以。在MySQL中违反约束条件时不能删除记录。你可能会做一个更新前的触发器来检查即将发生的约束冲突,但即使如此(从5.1开始),你也无法修改同一个表的数据(无论如何,这可能会导致无限循环)。

在塔德曼的回答之前只完成了一半。我个人喜欢他的想法。