Klucz w pracach to zamiast SELECT f_insert_tag(tag_p_id, _tag)
SELECT * FROM
f_insert_tag(tag_p_id, _tag)
Dla Postgresa 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 tutaj
Dla Postgresa 9.5 lub nowszego:
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 tutaj
Podstawy tutaj: