База данных содержит таблицу пользователей. Пользователь добавляется в таблицу всякий раз, когда его имя пользователя является частью данных, отправляемых в базу данных (т. Е. Через функцию), и имя пользователя должно быть уникальным в таблице. Одно имя пользователя также может появляться несколько раз при любом вызове функции.
Для каждого имени пользователя я хотел бы получить его существующий идентификатор или вставить его в таблицу пользователей и вернуть идентификатор.
Решение, которое я придумала, - это функция STABLE, которая сначала пытается выбрать из таблицы пользователей, а в случае неудачи вызывает вспомогательную функцию VOLATILE, которая пытается вставить в таблицу пользователя. Я предпочитаю STABLE, потому что результат функции будет таким же для остальной части транзакции, поэтому я хотел бы оптимизировать его в случае, когда имя пользователя было включено несколько раз, или когда оно передается другим функциям, которые также ищет его ID.
У меня вопрос: будет ли STABLE из моей начальной функции означать, что параллельная вставка (вызывающая исключение в вспомогательной функции) никогда не будет видна исходной функции и, таким образом, вызовет бесконечный цикл?
Я включил определения ниже.
CREATE SCHEMA orgnztn;
CREATE TABLE orgnztn.tUsers (
id serial NOT NULL,
usrid text NOT NULL,
PRIMARY KEY (id),
UNIQUE (usrid)
);
CREATE OR REPLACE FUNCTION orgnztn.getUserID (
IN p_usrid text
)
RETURNS integer
LANGUAGE plpgsql
STABLE
CALLED ON NULL INPUT
SECURITY INVOKER
AS $$
DECLARE
p_id integer;
BEGIN
IF p_usrid IS NULL THEN
RETURN NULL;
END IF;
p_usrid = upper(p_usrid);
LOOP
SELECT id INTO p_id
FROM orgnztn.tUsers
WHERE usrid = p_usrid
FETCH FIRST 1 ROWS ONLY;
IF found THEN
RETURN p_id;
END IF;
BEGIN
RETURN orgnztn.getUserID_helper(p_usrid);
EXCEPTION WHEN unique_violation THEN
-- loop
END;
END LOOP;
END;
$$;
CREATE OR REPLACE FUNCTION orgnztn.getUserID_helper (
IN p_usrid text
)
RETURNS integer
LANGUAGE plpgsql
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
AS $$
DECLARE
p_id integer;
BEGIN
INSERT INTO orgnztn.tUsers (usrid)
VALUES (p_usrid)
RETURNING id INTO p_id;
RETURN p_id;
END;
$$;