MySQL:只有在满足条件的情况下才更新字段。

94
可以在MySQL上执行UPDATE查询吗?只有在满足特定条件时才更新字段值。类似这样的操作是否可行?
UPDATE test
SET
    CASE
        WHEN true
        THEN field = 1
    END
WHERE id = 123

换句话说,只有在满足条件的情况下,"field"才会被更新,否则不会进行任何操作。 更新:我的示例查询并没有完全说明我的问题,因为可能还有其他字段需要在没有条件的情况下进行更新,换句话说:
UPDATE test
SET
    something = 1,        /*field that always gets updated*/
    CASE
        WHEN true
        THEN field = 1    /*field that should only get updated when condition is met*/
    END
WHERE id = 123

抱歉信息不足。

3
如果您想根据条件以不同的方式更新行,那么在更新查询中使用CASE是唯一的原因。如果您只想更新某些行,请将条件添加到WHERE子句中即可。 - SilverSnake
6个回答

167

是的!

这里有另一个例子:

UPDATE prices
SET final_price= CASE
   WHEN currency=1 THEN 0.81*final_price
   ELSE final_price
END

之所以能够这样工作,是因为MySQL在没有更改时不会更新行,正如文档中所述:(参见文档)

如果您将一列设置为其当前值,MySQL会注意到这一点并不对其进行更新。


8
只有当条件满足时,"field" 才会被更新,否则什么也不会发生。 - Hamlet Hakobyan
是的!正是我想要它做的。 - fedorqui
3
WHERE currency=1 是什么意思? - Hamlet Hakobyan
4
@fedorqui,根据您的查询目前看起来,您将更新当前不等于1的行,使其与已有值相同。这可能会触发更新触发器并产生其他影响,例如更新“ON UPDATE” TIMESTAMP列。 - SilverSnake
2
@fedorqui,我很荣幸地更新了您的答案,并附上了文档参考,说明为什么这实际上是有效的。 - radoh
显示剩余4条评论

50

在我看来,更易于阅读的另一种解决方案是:

UPDATE test 
    SET something = 1, field = IF(condition is true, 1, field) 
    WHERE id = 123

这个操作会在满足条件时将“field”设置为1(就像OP所举的例子),而在不满足条件时使用“field”的当前值。使用先前的值与不更改相同,因此你可以这样做。


1
是的,我同意,这看起来更美观,而且我也注意到mysql workbench语法的格式也是如此。我个人认为,这应该是这个查询的常见实践语法。 - DDeathlonger

13

试试这个:

UPDATE test
SET
   field = 1
WHERE id = 123 and condition

5
我再次给这个踩了个“反对票”……因为那根本不是解决问题的方法……我很困惑,人们为什么会投赞成票。 - Dominique
@Dominique,也许你被“condition”这个词的错误所困扰了? - Hamlet Hakobyan
1
WHERE条件的问题在于它作用于行级别而非字段级别。如果你想更新几个字段并且只想对其中一个字段设置条件,那么WHERE就不起作用了。它要么会导致整行被更新,要么不会影响其他字段。 - Zvi
2
我并没有把你和其他任何事物混淆,我只是知道你的建议完全是错误的,并且不符合 OP 的要求。你应该再读一遍问题。 - Dominique
@Dominique,我看到这个答案被很多人踩了,于是决定找出问题所在。作为一个具有分析思维的开发者,我仔细查看了原帖的编辑记录,结果发现,这个答案完全符合最初的问题要求。 - undefined

4

我们可以使用MySQL IF() 条件函数来解决问题:

UPDATE test
SET  field  = IF(something == 1{CONDITION}, 1 {NEW VALUE}, field)
WHERE `id` = 5

UPDATE servers SET port = IF(port != 21, 22, port) WHERE id = 123; 在我的情况下,如果不是仅限于21的Telnet端口,我想将SSH端口设置为22,否则请保留22。 - vimjet
3
应该用单等号而不是双等号吗? - Rob Sedgwick

3

另一种变化:

UPDATE test
SET field = IF ( {condition}, {new value}, field )
WHERE id = 123

这将会更新field的值为{new value},但仅当满足{condition}时才会被执行。

这个答案比被采纳的那个好多了! - Heitor
好的,我认为这是一个很好的回答,但是如果这个特定字段持续更新,性能会发生什么变化呢? - KaliBoy

-2
找到了带有AND条件的解决方案:
  $trainstrength = "UPDATE user_character SET strength_trains = strength_trains + 1, trained_strength = trained_strength +1, character_gold = character_gold - $gold_to_next_strength WHERE ID = $currentUser AND character_gold > $gold_to_next_strength";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接