在UPDATE语句中使用CASE根据条件更新特定列的T-SQL方法

132

我想知道这是否可能。如果条件为真,则要更新列x,否则要更新列y。

UPDATE table SET
     (CASE (CONDITION) WHEN TRUE THEN columnx
                       ELSE columny
      END)
= 25

我已经搜索了很多地方,尝试了一些方法,但是无法找到解决方案。我认为这不可能,但我想在这里问问看是否有人以前做过。


假设所有内容都在同一个表中,是的。您始终可以在事务中运行它,并在出现错误时回滚,以便自己查看。 - OMG Ponies
我不确定你的意思。我尝试为该列添加条件语句,但它并没有起作用。对于select语句,它可以正常工作,但对于update语句则不行。(从myTable中选择(case (condition) when true then columnx else columny end)...更新无法正常工作,我也能看出原因。似乎没有办法让它正常工作。) - pqsk
6个回答

210

您不能使用条件来更改查询的结构,只能更改涉及数据。您可以这样做:

update table set
    columnx = (case when condition then 25 else columnx end),
    columny = (case when condition then columny else 25 end)

语义上相同,但请注意 两列将始终被更新。这 可能 不会引起问题,但如果您的事务量很高,那么这可能会导致并发问题。

特别 实现您要求的功能,唯一的方法是使用动态SQL。然而,我鼓励您远离这种解决方案。上面的解决方案几乎肯定已经足够满足您的需求。


我同意关于动态SQL的观点。但是我的数据会受到影响吗?我的意思是,我不希望在某些条件下更改它。那么它只会重新插入已经存在的内容吗?对数据库的访问次数可能不会太多。 - pqsk
@pqsk:这不应该影响你的数据,它只会重新插入那些应该受影响的列中已经存在的内容。 - Adam Robinson
谢谢。我会选择这个。如此简单,甚至穴居人都能做到。哈哈。 - pqsk
1
@AdamRobinson 1.5年过去了,你知道更新单个列的更有效方法吗? - user1432124
@Somebodyisintrouble:更新单个列的唯一方法是使用不同的查询。 - Adam Robinson
是的,Adam指出的是正确的,在处理大量数据集和海量数据时,我们不应该在SET中使用CASE语句进行更新。我已经测试过了,发现即使是单行查询,这个查询也非常缓慢。点赞以表扬指出这个缺点。 - vikeng21

28
UPDATE  table
SET     columnx = CASE WHEN condition THEN 25 ELSE columnx END,
        columny = CASE WHEN condition THEN columny ELSE 25 END

1
你是刚刚复制了Adam的回答,还是这个内容来源于其他地方?哈哈,我才注意到。 - pqsk
1
@pqsk:我们的回复相隔约1分钟,所以我想我只是稍微快了一点点击提交按钮 ;) - Adam Robinson
27
@pqsk: 是的,我只是在 Adam 发布它之前 23 秒复制了他的回复。我是一个快速的复制粘贴者! - Quassnoi
2
@pqsk:如果你把光标放在“* min ago”上面,它会显示帖子的确切时间。 - Quassnoi
2
公平地说,尽管两者是相同的:如果亚当的回答在你之后出现,他确实详细阐述了一些。这就是为什么我标记他的回答为正确答案。不过还是谢谢你。 - pqsk
显示剩余3条评论

16

我知道这是一个非常老的问题,但这对我有用:

UPDATE TABLE SET FIELD1 =
CASE 
WHEN FIELD1 = Condition1 THEN 'Result1'
WHEN FIELD1 = Condition2 THEN 'Result2'
WHEN FIELD1 = Condition3 THEN 'Result3'
END;

2
注意:不符合任何条件的字段将在此查询中设置为“null”。 别忘了在“WHEN”语句之后设置一个“ELSE FIELD1”,以免触及其余数据。 - Glioburd

4

enter image description here

我想使用Case语句将我的联系电话从8018070777更改或更新为8018070999。

update [Contacts] set contactNo=(case 
when contactNo=8018070777 then 8018070999
else
contactNo
end)

enter image description here


3
为什么不使用以下查询语句: UPDATE [Contacts] SET contactNo = 8018070999 WHERE contactNo = 8018070777 - NewGuy

4

我知道这是一个非常老的问题,并且该问题已被标记为已解决。然而,如果有人遇到像我这样的情况,其中表格具有更新事件数据记录触发器,则会出现问题。两个列都将得到更新,并且日志将产生无用的条目。我的方法是

IF (CONDITION) IS TRUE
BEGIN
    UPDATE table SET columnx = 25
END
ELSE
BEGIN
    UPDATE table SET columny = 25
END

现在,这有另一个好处,就是它不会像上述解决方案那样对表格进行不必要的写入。

1
这是一个很好的观点和很好的替代方案!我不再使用导致这个线程的原始代码,但拥有不同的解决方案总是很好的,我认为这是一个很好的解决方案。 - pqsk

0

我相信你可以通过调整其他答案来省略更新“非期望”列:

update table set
    columnx = (case when condition1 then 25 end),
    columny = (case when condition2 then 25 end)`

据我理解,只有在满足条件时才会进行更新。

阅读了所有评论后,这是最有效的方法:

Update table set ColumnX = 25 where Condition1
 Update table set ColumnY = 25 where Condition1`

示例表格:

CREATE TABLE [dbo].[tblTest](
    [ColX] [int] NULL,
    [ColY] [int] NULL,
    [ColConditional] [bit] NULL,
    [id] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]

示例数据:

Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 0)
Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 0)
Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 1)
Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 1)
Insert into tblTest (ColX, ColY, ColConditional) values (1, null, null)
Insert into tblTest (ColX, ColY, ColConditional) values (2, null, null)
Insert into tblTest (ColX, ColY, ColConditional) values (null, 1, null)
Insert into tblTest (ColX, ColY, ColConditional) values (null, 2, null)

现在我假设你能编写一个处理 null 值的条件语句。在我的例子中,我假设你已经编写了这样一个条件语句,它能够评估为 True、False 或 Null。如果你需要帮助,请让我知道,我会尽力提供帮助。

现在运行这两行代码确实会将 X 改为 25,但前提是 ColConditional 为 True(1),并且将 Y 改为 25,但前提是 ColConditional 为 False(0)。

Update tblTest set ColX = 25 where ColConditional = 1
Update tblTest set ColY = 25 where ColConditional = 0

附言:原始问题或任何更新中从未提到过空值情况,但是正如您所看到的,这个非常简单的答案仍然可以处理它们。


1
这实际上是不起作用的。首先,如果列允许空值,则在未满足条件时将分配一个空值。在不允许空值的情况下,更新将失败。您最终的“高效”查询是无效的SQL,至少在TSQL中是如此。您是否在特定引擎上测试过并且对您有效? - pqsk
我在 SQL Server 2005 上测试过,结果完美无缺。但我真的很想知道为什么会被投反对票,并且希望看到一个例子,展示 NULL 值如何被更新。因为在我的上述测试中,NULL 值并没有被更新。我一直认为最简单的答案是最好的,如果我要处理数百万条记录的数据库,我肯定不想去更新不必要的行。 - John Greiner

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