Postgresql
在查詢中返回列是否已被目前查詢更改
我有一個像這樣的查詢
UPDATE my_table SET my_value = CASE WHEN random() > 0.5 THEN my_value * 2 ELSE my_value END RETURNING *;
現在,在
RETURNING
語句中,我想要一個布爾值,指示my_value
目前查詢是否已更改。假設,我不能將之前的值
my_value
作為參數傳遞給查詢。那麼,有沒有辦法獲得類似在 之後具有不同值的列的列表
UPDATE
?還是在 in 之前的狀態下獲取UPDATE
值RETURNING
?在我的範例中,我當然可以將結果放入
random()
CTE 中,例如WITH random_cte AS ( SELECT random() AS my_random ) UPDATE my_table SET my_value = CASE WHEN my_random > 0.5 THEN my_value * 2 ELSE my_value END FROM random_cte RETURNING *, my_random > 0.5 AS value_changed;
但這會使查詢有些膨脹。所以我想知道我是否可以以更優雅的方式做到這一點?
這兩個查詢是不等價的。第一個查詢將評估每一行的**
VOLATILE
**函式random()
,而第二個查詢在 CTE 中評估一次,因此my_random
對所有行都是相同的。不,CTE 不會被內聯。手冊:
但是,如果
WITH
查詢是非遞歸且無副作用的(即,它不SELECT
包含 volatile 函式),則可以將其折疊到父查詢中大膽強調我的。
但這可能只是建構測試時的一個意外。
任一查詢都會更新所有行,即使沒有任何變化。
為了獲得
value_changed
可靠的結果,請比較 pre-UPDATE
和 post-UPDATE
值:UPDATE my_table t SET my_value = CASE WHEN random() > 0.5 THEN t.my_value * 2 ELSE t.my_value END FROM (SELECT id, my_value FROM my_table) pre WHERE t.id = pre.id RETURNING t.*, t.my_value IS DISTINCT FROM pre.my_value AS value_changed;
id
是 PK 或任何其他(組合)唯一的非空列。
random() > 0.5
可以true
並且my_value
仍然保持不變。想想NULL
或0
。並發寫入負載下存在潛在的競爭條件。看:
如果您的案例真的那麼簡單(只有一個列要更新),您寧願從一開始就禁止空更新。看: