sql >> Databáze >  >> RDS >> PostgreSQL

Závodní podmínka mezi SELECT a INSERT pro více sloupců

Klíč na práci je SELECT f_insert_tag(tag_p_id, _tag) místo

SELECT * FROM f_insert_tag(tag_p_id, _tag)

Pro 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 zde

Pro Postgres 9.5 nebo novější:

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 zde

Základy zde:




  1. Co je efektivnější:Více tabulek MySQL nebo jedna velká tabulka?

  2. GROUP BY / zmatek agregačních funkcí v SQL

  3. Má replikace mySQL okamžitou konzistenci dat?

  4. Chyba připojení SSL při používání konektoru MySQL s Pythonem