使用CASE选择UPDATE查询中的列?


13

我可以CASE用来选择要在SELECT查询(Postgres)中显示的列,如下所示:

SELECT CASE WHEN val = 0 THEN column_x
            WHEN val = 1 THEN column_y
            ELSE 0
       END AS update, ...

UPDATE在Postgres中执行查询时(即选择应更新哪些列),是否有可能完全相似?我假设没有,因为我对此一无所获,但是也许有人有一个聪明的选择(除了使用过程,还是使用CASE来更新每个列,以确定是应该为该列的值分配一个新值还是简单地重新分配现有值)值)。如果没有简单的选择,我当然也会接受。

额外信息:在我的情况下,我有14列可能要更新的列,每个匹配的行仅更新一个(要更新的表在查询中与另一个连接)。要更新的行数很可能会有所不同,可能是数十行或数百行。我相信加入条件的索引已经到位。

Answers:


26

如果您指定应更新的列,则该列将始终被更新,但是您可以根据条件更改您有条件输入的值并放回原始值。就像是:

UPDATE some_table
SET    column_x = CASE WHEN should_update_x THEN new_value_for_x ELSE column_x END
     , column_y = CASE WHEN should_update_y THEN new_value_for_y ELSE column_y END
     , column_z = CASE WHEN should_update_z THEN new_value_for_z ELSE column_z END
FROM   ...

因此,如果不适合更新特定列的条件,则只需反馈其当前值即可。

请注意,除非您在过滤ON和WHERE子句时明确指定了这种情况,否则匹配的每一行都会看到更新(即使所有列最终都设置为它们已经具有的值),这可能是性能问题(是写操作,索引将被更新,适当的触发器将触发,...)如果不缓解。


感谢您提供有关所有内容更新的提示,如果此操作很慢,我可能会建议@Colin't Hart建议使用多个更新语句。
newenglander

您可以通过确保ON和WHERE子句过滤掉不需要更改的所有行来缓解该问题,但这可能意味着在SET子句和WHERE子句中都重复所有条件(除非进行更简单的总体检查等于所有这些条件总和的100%)。到那时,该方法可能仍然更有效,但是多重更新方法可能更易于维护。
David Spillett

要知道也是更新到相同值的列将导致所创建的重做,看到orainternals.wordpress.com/2010/11/04/...
科林“T哈特

@Colin:是的,任何更新都将通过数据库的事务日志,其中包括由于将字段更新为以前具有相同值而本质上为NoOps的更新。如果使用复制,差异备份,日志传送等方式,则可能会立即导致性能问题,这可能是一个重要因素,因为额外的行更新操作将增加这些操作所需的空间/带宽。
David Spillett

感谢你们俩的提示,就我而言,单个update语句运行良好。
newenglander 2013年

5

您有多少种不同的列组合要更新?整个表中将更新多少行?是否存在索引以快速访问要更新的行?

根据对这些问题的答案,您可能能够执行多个更新语句,对于您要更新的每一列一个,并将条件放在更新的where子句中该列的值上,以便该列更新零行。具有错误的值。

尝试考虑基于集合的情况,不要假设update需要更新主键找到的一行。


感谢你的回答。我向问题添加了更多信息,希望它是可以理解的。这是带有多个更新语句的一个很好的选择(我更喜欢一个更新语句,但是我看到那里有一个优势)。
newenglander

这可能是我正在寻找的答案,但是您的意思是将update column_x = new_value_for_x放在@val = 0的地方。我可能会尝试类似的方法。看起来很好笑。如果val = 0开始更新column_x = new_value_for_x等,这不是一件容易的事
CashCow

-1
update Practicing  -- table you will be updating
 set email = case -- column you will be updating
    when FName = 'Glenn' then 'Ace@Assasin.com'
       when FName = 'Riddick' then 'fallguy@Drunk.com'
       when FName = 'Jeffrey' then 'sorcerer@wizcom'
       else email
    end

此更新仅更新一列,而询问者想知道如何根据条件更新不同的列。
Colin't Hart
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.