2012-11-09 102 views
18

我有這樣的查詢(在一個函數)不更新列:如果更新值爲null

UPDATE some_table SET 
    column_1 = param_1, 
    column_2 = param_2, 
    column_3 = param_3, 
    column_4 = param_4, 
    column_5 = param_5 
WHERE id = some_id; 

哪裏param_x是我的函數的參數。有沒有辦法不更新這些列,參數爲NULL?例如 - 如果param_4param_5NULL,則只更新前三列併爲column_4column_5保留舊值。

我現在做的方式是:

SELECT * INTO temp_row FROM some_table WHERE id = some_id; 

UPDATE some_table SET 
    column_1 = COALESCE(param_1, temp_row.column_1), 
    column_2 = COALESCE(param_2, temp_row.column_2), 
    column_3 = COALESCE(param_3, temp_row.column_3), 
    column_4 = COALESCE(param_4, temp_row.column_4), 
    column_5 = COALESCE(param_5, temp_row.column_5) 
WHERE id = some_id; 

有沒有更好的辦法?

+0

我認爲這是一段路要走。 –

回答

39

下降SELECT語句,沒有必要,只是使用當前值:

UPDATE some_table SET 
    column_1 = COALESCE(param_1, column_1), 
    column_2 = COALESCE(param_2, column_2), 
    column_3 = COALESCE(param_3, column_3), 
    column_4 = COALESCE(param_4, column_4), 
    column_5 = COALESCE(param_5, column_5) 
WHERE id = some_id; 
8

此外,爲了避免更新:

UPDATE some_table SET 
    column_1 = COALESCE(param_1, column_1), 
    column_2 = COALESCE(param_2, column_2) 
    ... 
WHERE id = some_id; 
AND (param_1 IS DISTINCT FROM column_1 OR 
     param_2 IS DISTINCT FROM column_2 OR 
     ... 
    ); 
10

絕招,謝謝Przemek,弗蘭克&歐文!

我建議對Erwin的答案進行小修改以避免空的更新。如果任何參數爲null(意思是:「使用舊值」),即使行值沒有更改(第一次更新後),每次更新該行。

通過添加 「param_x IS NOT NULL」,我們避免了空更新:

UPDATE some_table SET 
    column_1 = COALESCE(param_1, column_1), 
    column_2 = COALESCE(param_2, column_2), 
    ... 
WHERE id = some_id 
AND (param_1 IS NOT NULL AND param_1 IS DISTINCT FROM column_1 OR 
     param_2 IS NOT NULL AND param_2 IS DISTINCT FROM column_2 OR 
    ... 
); 
+2

對,這樣更好。如果所有涉及的列都被定義爲「NOT NULL」,那麼我的版本已經在參數中覆蓋了NULL。對於OP中在UPDATE中不允許新的NULL值的情況,這不是不可能的。 –