在Postgres中使用DELETE的返回值进行UPDATE

时间:2013-08-01 14:46:03

标签: postgresql syntax sql-update sql-delete

我需要使用从另一个表中删除的值来更新表。情况是评论投票记分员类似于SO上的评分投票记分员。我正在使用python来处理postgres,但这不应该有所作为。

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语句,它会起作用,我在这里缺少什么?我想在更新中使用返回值。这可能吗?一切都有帮助。

相关架构:

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

history.vote通常为1-1

1 个答案:

答案 0 :(得分:18)

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或更新