2015-02-06 97 views
0

更新多列我有以下UPDATE语句使用相同的SQL Server case语句

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语句来更新两列?

+0

我相信你需要复制粘贴case-when子句多次 – abatishchev 2015-02-06 20:33:49

+0

问题只是别名PHP?如果你离开它,它会起作用吗? – 2015-02-06 20:34:48

+0

@JamesZ它不会我需要那些别名......有一些底层JOINS – 2015-02-06 20:45:58

回答

1

基本上这是不可能的。您可以将CASE..END发挥作用,并呼吁它这样,但影响discutable ...

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) 
1

或者如果逻辑如此简单,您可以使用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 
2

是否有可能使用一个case语句来更新两列?

编号A 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,数据几乎设置之前,语句的执行,因为他们是。

0

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

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 

附加到聚结的“+空”每个输入参数,以确保表达被执行和结果存储在变量,但不返回表达式的结果通过合并功能。

经过MySQL测试。