2013-08-01 9 views
7

別のテーブルから削除した値を使用してテーブルを更新する必要があります。状況はSOのものと同様のコメント投票スコアキーパーです。私はポストグルを動作させるためにPythonを使用していますが、違いはありません。PostgresのUPDATEにDELETEの戻り値を使用する

query=""" 
UPDATE comment SET score=score-(DELETE FROM history 
           WHERE commentId=%(commentId)s AND 
             userIdentity=%(userIdentity)s RETURNING vote) 
WHERE commentId=%(commentId)s; 
""" 
cursor.execute(query, data) 

エラーが(DELETE FROMで生じます。構文エラーが発生します。 DELETEステートメントをSELECTステートメントに置き換えることができます。これは機能しますが、ここには何か不足していますか?私は、更新で戻り値を使用したい。これは可能ですか?何かが助けます。

Releventスキーマ:

CREATE TABLE history (
    commentId bigint, 
    vote int, 
    userIdentity varchar(256), 
); 
CREATE TABLE comment (
    id bigint, 
    score bigint, 
); 

history.voteが正常に1-1です。

答えて

16

PostgreSQLでは、副問合せとして、UPDATE文とDELETE文を混在させることはできません。

あなたは少し異なる戦略を使用することができます - 更新可能CTE

 
postgres=# WITH t1 AS (DELETE FROM foo RETURNING *), 
       t2 AS (INSERT INTO deleted 
          SELECT * FROM t1 RETURNING *) 
      SELECT max(a) FROM t2; 

ので

 
postgres=# CREATE TABLE comment(id int, score int); 
CREATE TABLE 
postgres=# CREATE TABLE history(id int, comment_id int, vote int); 
CREATE TABLE 
postgres=# INSERT INTO comment values(1,10); 
INSERT 0 1 
postgres=# INSERT INTO comment values(2,20); 
INSERT 0 1 
postgres=# INSERT INTO history values(1,1,5); 
INSERT 0 1 
postgres=# WITH t1 AS (DELETE FROM history 
         WHERE id=1 
         RETURNING comment_id, vote) 
      UPDATE comment SET score=score-t1.vote 
      FROM t1 
      WHERE t1.comment_id=comment.id; 
UPDATE 1 
postgres=# select * from comment; 
id | score 
----+------- 
    2 | 20 
    1 |  5 
(2 rows) 

注意:これは、9.1またはそれ以降

+0

を必要とするこれが歴史の中で投票を取り除く、意図したとおりに動作します投票スコアを原子的に更新する。ありがとう! – JDong

+0

うわー、あなたは 'WITH'で1つのステートメントでどれほどのことができるのか驚くほどです。 – danneu

関連する問題