Upsert with a transaction

前端 未结 2 1527
耶瑟儿~
耶瑟儿~ 2020-12-02 03:00

I\'m using Spring with PostgreSQL and I try to do a sort of UPSERT by using a code like this:

jt.update(\"delete from A where id = 1\")
jt.update(\"insert in         


        
2条回答
  •  旧时难觅i
    2020-12-02 03:52

    Assuming this simple table:

    CREATE TABLE tbl(id int primary key, value int);
    

    This function almost 100% secure (see comments) for concurrent transactions.:

    CREATE OR REPLACE FUNCTION f_upsert(_id int, _value int)
      RETURNS void AS
    $func$
    BEGIN
    LOOP
       UPDATE tbl SET value = _value WHERE  id = _id;
    
       EXIT WHEN FOUND;
    
       BEGIN
          INSERT INTO tbl (id, value)
          VALUES (_id, _value);
    
          RETURN;
    
       EXCEPTION WHEN UNIQUE_VIOLATION THEN     -- tbl.id has UNIQUE constraint.
          RAISE NOTICE 'It actually happened!'; -- hardly ever happens
       END;
    
    END LOOP;
    END
    $func$ LANGUAGE plpgsql;
    

    Call:

    SELECT f_upsert(2, 2);
    

    It's very similar to this INSERT / SELECT case with more explanation and links:

    • Is SELECT or INSERT in a function prone to race conditions?

提交回复
热议问题