9

這已被問了多次herehere,但沒有一個答案適合我的情況,因爲我不想在PL/PgSQL函數中執行我的更新語句並使用GET DIAGNOSTICS integer_var = ROW_COUNT得到的影響行UPDATE語句在RAW plpgsql

我必須在原始SQL中執行此操作。

例如,在MS SQL SERVER,我們有可能像使用@@ ROWCOUNT如下:

UPDATE <target_table> 
SET Proprerty0 = Value0 
WHERE <predicate>; 
SELECT <computed_value_columns> 
FROM <target> 
WHERE @@ROWCOUNT > 0; 

在一個往返到我知道如果更新全成和獲得的計算值回數據庫。

什麼可以用來代替'@@ ROWCOUNT'? 有人可以確認這在這個時候實際上是不可能的嗎?

在此先感謝。

編輯1:我確認我需要使用原始SQL(我在原始描述中寫了「原始plpgsql」)。

在試圖讓我的問題更加清楚,請考慮更新語句隻影響一行,想想樂觀併發:

  1. 客戶首先做了SELECT聲明。

  2. 他構建UPDATE並知道哪些數據庫計算列將包含在SELECT子句中。除此之外,謂詞包括每次更新行時計算的時間戳。

  3. 所以,如果我們有1行返回,那麼一切都OK。如果沒有行被返回,那麼我們知道有前一次更新,並且客戶端可能需要刷新數據,然後再次嘗試更新子句。這就是爲什麼我們需要知道在返回計算列之前有多少行受update語句影響。如果更新失敗,則不應返回任何行。

+1

請務必在提問中提及您的PostgreSQL版本。 –

+3

所以你**不要**想在PL/pgSQL中做,但在SQL中。否則,您*可能會使用GET GETNAGNOSTICS –

+0

@CraigRinger:請參閱相應的標籤。 –

回答

10

你想要的東西目前不可能用你描述的形式,但我認爲你可以用UPDATE ... RETURNING做你想做的。請參閱UPDATE ... RETURNING in the manual

UPDATE <target_table> 
SET Proprerty0 = Value0 
WHERE <predicate> 
RETURNING Property0; 

很難確定,因爲您提供的示例非常抽象以至於毫無意義。

你也可以使用一個wCTE,它允許更復雜的情況:

WITH updated_rows AS (
    UPDATE <target_table> 
    SET Proprerty0 = Value0 
    WHERE <predicate> 
    RETURNING row_id, Property0 
) 
SELECT row_id, some_computed_value_from_property 
FROM updated_rows; 

common table expressions (WITH queries)depesz's article on wCTEs。基於問題增加了一些細節


UPDATE,這裏是一個使用UPDATE ... RETURNING演示:

CREATE TABLE upret_demo(
    id serial primary key, 
    somecol text not null, 
    last_updated timestamptz 
); 

INSERT INTO upret_demo (somecol, last_updated) VALUES ('blah',current_timestamp); 

UPDATE upret_demo 
SET 
    somecol = 'newvalue', 
    last_updated = current_timestamp 
WHERE last_updated = '2012-12-03 19:36:15.045159+08' -- Change to your timestamp 
RETURNING 
    somecol || '_computed' AS a, 
    'totally_new_computed_column' AS b; 

輸出運行的第一時間時:

  a   |    b    
-------------------+----------------------------- 
newvalue_computed | totally_new_computed_column 
(1 row) 

當再次運行,它將不起作用並且不返回任何行。

如果您在結果集中執行了更復雜的計算,則可以使用wCTE,以便加入更新結果並執行其他複雜的操作。

WITH upd_row AS (
    UPDATE upret_demo SET 
    somecol = 'newvalue', 
    last_updated = current_timestamp 
    WHERE last_updated = '2012-12-03 19:36:15.045159+08' 
    RETURNING id, somecol, last_updated 
) 
SELECT 
    'row_'||id||'_'||somecol||', updated '||last_updated AS calc1, 
repeat('x',4) AS calc2 
FROM upd_row; 

換句話說:使用UPDATE ... RETURNING,或者直接以產生計算出的行,或在一個可寫爲CTE更復雜的情況。

+0

可寫CTE從9.2版開始工作。可寫的CTE很棒!我不明白爲什麼它們在實施之前花了很長時間,大多數DBMS品牌仍然不支持它,我不能再沒有它了。 –

+0

謝謝! UPDATE ... RETURNING按預期工作。 –