Hi David,

thanks for your advise, as I am new with postgresql..
I try to use LOCK as below, but it does not returning pid?
what I missed?

BEGIN TRANSACTION;
LOCK TABLE test IN ACCESS EXCLUSIVE MODE;
WITH s AS (
   SELECT pid FROM test WHERE area = 'test4'
), i AS (
   INSERT INTO test (area)
   SELECT 'test4'
   WHERE NOT EXISTS (SELECT 1 FROM s)
   RETURNING pid
)
UPDATE area
SET last_update = CURRENT_TIMESTAMP
WHERE pid = (SELECT pid FROM s UNION SELECT pid FROM i)
RETURNING pid;
COMMIT TRANSACTION;


On Thu, May 16, 2019 at 4:25 PM David Rowley <david.row...@2ndquadrant.com>
wrote:

> On Thu, 16 May 2019 at 21:13, Winanjaya Amijoyo
> <winanjaya.amij...@gmail.com> wrote:
> > When record not found then insert and return pid value or if not found
> then update based on pid and again return its pid.
>
> You could do something like:
>
> WITH s AS (
>    SELECT pid FROM test WHERE area = 'test5'
> ), i AS (
>    INSERT INTO test (area)
>    SELECT 'test5'
>    WHERE NOT EXISTS (SELECT 1 FROM s)
>    RETURNING pid
> )
> UPDATE area
> SET last_update = CURRENT_TIMESTAMP
> WHERE pid = (SELECT pid FROM s UNION SELECT pid FROM i)
> RETURNING pid;
>
> but be warned, it's could all fall over as soon as you have concurrent
> sessions running this at the same time.  You could protect against
> that by doing some advisory locking (
> https://www.postgresql.org/docs/11/explicit-locking.html#ADVISORY-LOCKS
> ), or taking an access exclusive lock on "test".
>
> --
>  David Rowley                   http://www.2ndQuadrant.com/
>  PostgreSQL Development, 24x7 Support, Training & Services
>

Reply via email to