On 08/28/2014 06:22 AM, Jim Garrison wrote:
> Given (pseudocode)
> 
>     CREATE TABLE kvstore (
>         k varchar primary key,
>         v varchar);
> 
>     CREATE OR REPLACE FUNCTION store_key_value_pair(k varchar, v varchar) 
> returns boolean as $$
>     BEGIN
>       INSERT INTO kvstore (k, v)
>       SELECT :k, :v
>       WHERE NOT EXISTS (select 1 from kvstore where k = :k);
>       RETURN FOUND;
>     END;
>     $$ LANGUAGE plpgsql;
> 
> I have a few questions:
> 
> 1) Does INSERT statement set FOUND based on whether or not the row was 
> inserted?

> 2) If this is invoked without a transaction in progress, is there any 
> guarantee of atomicity between checking the EXISTS and attempting to insert 
> the row?  If this is being executed in two (or more) sessions, can the SELECT 
> succeed but then have the INSERT fail with a duplicate-key exception?

This code can still fail with a unique violation, yes, as the select can
occur in both transactions then the insert in both.

> 3) Will the behavior be different if the invoking processes have a 
> transaction in progress?

No, because all functions run in transactions. There is no such thing as
"not in a transaction" in PostgreSQL (except for a few special system
management commands).

If it's in a SERIALIZABLE transaction instead of the default READ
COMMITTED then it might fail with a serialization failure instead of a
unique violation, but it'll still fail.

Please read the detailed guidance on this problem that already exists:

http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE

http://www.depesz.com/2012/06/10/why-is-upsert-so-complicated/

http://stackoverflow.com/questions/1109061/insert-on-duplicate-update-in-postgresql



-- 
 Craig Ringer                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general

Reply via email to