sql >> Database >  >> RDS >> PostgreSQL

Racevoorwaarde tussen SELECT en INSERT voor meerdere kolommen

De sleutel in de maak is SELECT f_insert_tag(tag_p_id, _tag) in plaats van

SELECT * FROM f_insert_tag(tag_p_id, _tag)

Voor Postgres 9.4

CREATE FUNCTION f_insert_tag(_tag_id int, _tag text, OUT _tag_id_ int, OUT _tag_ text) 
AS
$func$
 BEGIN
   INSERT INTO t(tag_id, tag)
   VALUES (_tag_id, _tag)
   RETURNING t.tag_id, t.tag
   INTO  _tag_id_, _tag_;

   EXCEPTION WHEN UNIQUE_VIOLATION THEN
      -- catch exception, return NULL
 END
$func$  LANGUAGE plpgsql;


CREATE FUNCTION f_tag_id(_tag_id int, _tag text, OUT _tag_id_ int, OUT _tag_ text) AS
$func$
BEGIN
LOOP
   SELECT t.tag_id, t.tag
   FROM   t
   WHERE  t.tag = _tag

   UNION ALL
   SELECT *                                              -- !!!
   FROM   f_insert_tag(_tag_id, _tag)
   LIMIT  1

   INTO _tag_id_, _tag_;

   EXIT WHEN _tag_id_ IS NOT NULL;  -- else keep looping
END LOOP;
END
$func$ LANGUAGE plpgsql;

db<>fiddle hier

Voor Postgres 9.5 of hoger:

CREATE FUNCTION f_tag_id(_tag_id int, _tag text, OUT _tag_id_ int, OUT _tag_ text) AS
$func$
BEGIN
LOOP
   SELECT t.tag_id, t.tag
   FROM   t
   WHERE  t.tag = _tag
   INTO   _tag_id_, _tag_;

   EXIT WHEN FOUND;

   INSERT INTO t (tag_id, tag)
   VALUES (_tag_id, _tag)
   ON     CONFLICT (tag) DO NOTHING
   RETURNING t.tag_id, t.tag
   INTO   _tag_id_, _tag_;

   EXIT WHEN FOUND;
END LOOP;
END
$func$  LANGUAGE plpgsql;

db<>fiddle hier

Basis hier:




  1. kolom bestaat niet, zelfs niet bij gebruik van het trefwoord 'as'

  2. Hoe te controleren of een kolomwaarde expliciet is opgegeven in een PL/SQL BEFORE UPDATE-trigger?

  3. Hoe kunnen miljoenen statistische records efficiënt worden opgeslagen?

  4. Java - zoek de eerste oorzaak van een uitzondering