In this scenario I have 2 tables: a task_pool table and an orders table.
task_pool
| task_id (key) | order_id(int) | status(int) | expire_time(timestamp) |
|---|---|---|---|
| 20 | 1 | 0 | [timestamp] |
| 25 | 2 | 1 | [timestamp] |
orders
| order_id (key) | order_info(varchar) | order_datetime(timestamp) |
|---|---|---|
| 0 | "info" | [timestamp] |
| 1 | "info" | [timestamp] |
Right now I retreive order_info and order_datetime from the orders table using the related order_id from task table, using this query.
WITH t AS (
SELECT
task_id,
order_id,
status
FROM task_pool
WHERE
task_id = $1
AND
(status = 0 OR status = 1)
)
SELECT t.order_id, t.status,
order_info, order_datetime
FROM orders
INNER JOIN t ON orders.order_id=t.order_id`,
[req.body.task_id]
This works (the most efficient way, I don't know). It will only retrieve 1 row since task_id is unique index key.
What I am trying to do, is check IF t.status=0, and if so UPDATE expire_time to expire_time + 10 minutes, and status to 1.
I know I COULD check the results.rows[0] back in Node.js, and if status==0, make another pg query to update that row's expire_time and status.
However, I would prefer to do it all in the original query, unless it unadvised.
Something like:
WITH t AS (
SELECT
task_id,
order_id,
status
FROM task_pool
WHERE
task_id = $1
AND
(status = 0 OR status = 1)
)
**IF t.status = 0 THEN
UPDATE
task_pool
SET
status = 1, expire_time = expire_time + (10 * interval '1 minute')
WHERE
task_id = $1
END IF;**
SELECT t.order_id, t.status,
order_info, order_datetime
FROM orders
INNER JOIN t ON orders.order_id=t.order_id`,
[req.body.task_id]
Is this possible?
You can trade your
selectfor anupdate..returningthat targets the same row, but updates it based on your conditions, then returns the new values:You might want to decrease the table
fillfactorto let it fit the new values on the same pages - even when theupdateis unnecessary, the row still gets updated with the same values (theelses).You could also split this into two CTEs, one
select, another withupdate..returning, thenunionthose. That way no update is performed if it isn't necessary.If your target row didn't meet the
updatecriteria, thatupdateisreturningnothing, and the only values coming out of theunionare those from theselectwhich applied the opposite logic.