2013-08-01 21 views
7

我需要使用從另一個表中刪除的值更新表。這種情況是一個類似於SO的評論投票記分員。我使用python來運行postgres,但這不應該有所作爲。在Postgres中使用DELETE的UPDATE返回值更新

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;會出現語法錯誤。我可以用SELECT聲明替換DELETE聲明,它會起作用,在這裏有什麼我不在的地方?我想在更新中使用返回值。這可能嗎?任何幫助。

培訓相關的模式:

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 WITH語句中你可以做多少事情是令人驚訝的。 – danneu