web-dev-qa-db-ja.com

RAWplpgsqlのUPDATEステートメントによる影響を受ける行の取得

これは何度も尋ねられました ここここ ですが、PL/PgSQL関数で更新ステートメントを実行したくないので、私の場合はどの答えも適切ではありませんGET DIAGNOSTICS integer_var = ROW_COUNTを使用します。

これは生のSQLで行う必要があります。

たとえば、MS SQL SERVERには、次のように使用できる@@ ROWCOUNTがあります。

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

データベースへの1回のラウンドトリップで、更新が成功したかどうかがわかり、計算された値が返されます。

'@@ ROWCOUNT'の代わりに何を使用できますか?現時点ではこれが実際には不可能であることを誰かが確認できますか?

前もって感謝します。

EDIT 1:生のSQLを使用する必要があることを確認しました(元の説明に「rawplpgsql」と書きました)。

私の質問をより明確にするために、更新ステートメントは1つの行にのみ影響することを考慮し、楽観的並行性について考えてください。

  1. クライアントは最初にSELECTステートメントを実行しました。

  2. 彼はUPDATEを作成し、どのデータベース計算列をSELECT句に含めるかを知っています。特に、述語には、行が更新されるたびに計算されるタイムスタンプが含まれます。

  3. したがって、1行が返される場合は、すべて問題ありません。行が返されない場合は、以前に更新があったことがわかり、クライアントは句を再度更新する前にデータを更新する必要がある場合があります。これが、計算列を返す前に、updateステートメントの影響を受ける行数を知る必要がある理由です。更新が失敗した場合、行は返されません。

12
Olivier MATROT

あなたが望むことは、あなたが説明する形では現在不可能ですが、私はあなたがUPDATE ... RETURNINGであなたが望むことをすることができると思います。 マニュアルのUPDATE ... RETURNING を参照してください。

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;

一般的なテーブル式(WITHクエリ) および wCTEに関するdepeszの記事 を参照してください。


[〜#〜] 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;

1回目の実行時の出力:

         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で使用します。

14
Craig Ringer