【问题标题】:Update multiple columns using same SQL server case statement使用相同的 SQL Server 案例语句更新多个列
【发布时间】:2015-02-06 20:30:52
【问题描述】:

我有以下 UPDATE 语句

UPDATE PAYMENT_HISTORY
SET request_status_id =
CASE
  WHEN PHP.request_status_id = PHP.prevRequest_status_id THEN NULL 
  ELSE PHP.request_status_id
END,
  is_changed =
CASE
  WHEN PHP.request_status_id = PHP.prevRequest_status_id THEN 0
  ELSE 1
END    

是否可以使用单个 case 语句更新两列?

【问题讨论】:

  • 我认为您需要多次复制粘贴 case-when 子句
  • 问题只是别名PHP?如果你把它排除在外,它会起作用吗?
  • @JamesZ 我不需要那些别名...那里有一些潜在的联接
  • 如果您遗漏了 SQL 的重要部分,您将很难为您提供帮助
  • 您想避免一遍又一遍地重复相同的情况吗?不,一般不会。你真的只是想更新几行吗? WHERE PHP.request_status_id <> PHP.prevRequest_status_id。 (我知道这并不能完全处理你的null。)

标签: sql sql-server tsql case-when


【解决方案1】:

请参阅 BOL 以获取更新子句:https://msdn.microsoft.com/en-us/library/ms177523.aspx

特别是column_name = { expression | DEFAULT | NULL }

表达式只允许在右侧,因此您不能编写表达式来选择要更新的列。

【讨论】:

    【解决方案2】:

    是否可以使用单个 case 语句更新两列?

    没有。 CASE 表达式有一个原子值。单个CASE 表达式不能有两个字段的值。您不能通过一次使用 CASE ... END 同时设置 request_status_idis_changed

    可以在同一 UPDATE 语句中更新两个字段,但不能在同一 CASE 表达式中更新。

    但是,您的表达没有有问题,并且您在这里的作业不会相互影响。当语句开始执行时,读取的数据被锁定。它使用语句运行之前存在的表。

    考虑:

    CREATE TABLE TestTable (
        Odd TINYINT NOT NULL,
        Even TINYINT NOT NULL,
        PRIMARY KEY (Odd, Even)
    );
    
    INSERT INTO TestTable (Odd, Even) VALUES (1, 2);
    INSERT INTO TestTable (Odd, Even) VALUES (3, 4);
    INSERT INTO TestTable (Odd, Even) VALUES (5, 6);
    INSERT INTO TestTable (Odd, Even) VALUES (7, 8);
    
    SELECT * FROM TestTable;
    
    UPDATE TestTable SET Odd = Even, Even = Odd;
    
    SELECT * FROM TestTable;
    

    SQLFiddle

    除非你正在做一些奇怪的事情,比如递归 CTE,否则数据几乎都是在语句执行之前设置的。

    【讨论】:

      【解决方案3】:

      基本上不可能。您可以将 CASE..END 移动到功能并以这种方式调用它,但影响是可忽略的......

      UPDATE PAYMENT_HISTORY
      SET 
          request_status_id = dbo.fnCalc(PHP.request_status_id, PHP.prevRequest_status_id, 1),
          is_changed = dbo.fnCalc(PHP.request_status_id, PHP.prevRequest_status_id, 2)
      

      【讨论】:

        【解决方案4】:

        或者如果逻辑这么简单,你可以使用 2 次更新来完成,第二次更新是基于第一次更新的结果。但同样,你需要有理由这样做。

        UPDATE PAYMENT_HISTORY
          SET request_status_id =
           CASE
             WHEN PHP.request_status_id = PHP.prevRequest_status_id THEN NULL 
             ELSE PHP.request_status_id
           END
        
        UPDATE PAYMENT_HISTORY SET 
          is_changed = 
            CASE
              WHEN request_status_id is NULL THEN 0
              ELSE 1
            END    
        

        或者更有效的执行(第二次更新将只更新需要更新的行)

        UPDATE PAYMENT_HISTORY
          SET 
           request_status_id =
             CASE
               WHEN PHP.request_status_id = PHP.prevRequest_status_id THEN NULL 
               ELSE PHP.request_status_id
             END,
           is_changed=0
        
        
        UPDATE PAYMENT_HISTORY SET 
            is_changed = 1
          WHERE 
            request_status_id is not NULL 
        

        【讨论】:

          【解决方案5】:

          是的,可以通过使用变量来实现。

          UPDATE PAYMENT_HISTORY
          SET request_status_id =
          CASE
            WHEN PHP.request_status_id = PHP.prevRequest_status_id 
              THEN coalesce((@ischanged:=0)+null,NULL) 
              ELSE coalesce((@ischanged:=1)+null,PHP.request_status_id)
            END,
            is_changed = @ischanged
          

          一般:

          UPDATE mytable
          SET
            a = CASE 
              WHEN [condition1]
                THEN coalesce((@b:= [b expression]) +null, (@c:= [c expression]) +null, [a expression])
              WHEN [condition2]
                THEN coalesce((@b:= [b expression]) +null, (@c:= [c expression]) +null, [a expression])
              ELSE coalesce((@b:= [b expression]) +null, (@c:= [c expression]) +null, [a expression])
              END,
            b = @b,
            c = @c
          

          附加到 coalesce '+null' 的每个输入参数,以确保执行表达式并将结果存储在变量中,但表达式的结果不会由 coalesce 函数返回。

          在 MySQL 上测试。

          【讨论】:

            猜你喜欢
            • 2012-04-24
            • 2014-06-19
            • 1970-01-01
            • 1970-01-01
            • 2015-02-27
            • 1970-01-01
            • 1970-01-01
            • 2020-05-17
            • 2011-05-05
            相关资源
            最近更新 更多