2015-02-06 99 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測試。