I need to update a table using a value deleted from another table. The situation is a comment vote scorekeeper similar to the one on SO. I'm using python to work the postgres, but that shouldn't make a difference.
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)
The error arises at (DELETE FROM
; a syntax error arises. I can replace the DELETE
statement with a SELECT
statement and it will work, is there something I am missing here? I want to use the returning value in an update. Is this possible? Anything helps.
Relevent schema:
CREATE TABLE history (
commentId bigint,
vote int,
userIdentity varchar(256),
);
CREATE TABLE comment (
id bigint,
score bigint,
);
history.vote is normally 1
or -1
.
The standard DELETE statement in SQL returns the number of deleted rows. In PostgreSQL you can make DELETE statement return something else. You can return all rows that have been deleted. You can return the columns of your choice.
A common shorthand is RETURNING * , which selects all columns of the target table in order. In an INSERT , the data available to RETURNING is the row as it was inserted. This is not so useful in trivial inserts, since it would just repeat the data provided by the client.
Single-Table Syntax. The DELETE statement deletes rows from tbl_name and returns the number of deleted rows.
The optional RETURNING clause causes INSERT to compute and return value(s) based on each row actually inserted (or updated, if an ON CONFLICT DO UPDATE clause was used). This is primarily useful for obtaining values that were supplied by defaults, such as a serial sequence number.
PostgreSQL doesn't allow mix UPDATE and DELETE statements as subquery.
You can use a little bit different strategy - updateable CTE
postgres=# WITH t1 AS (DELETE FROM foo RETURNING *), t2 AS (INSERT INTO deleted SELECT * FROM t1 RETURNING *) SELECT max(a) FROM t2;
so
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)
Attention: It require 9.1 or newer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With