#sql #postgresql #triggers
#sql #postgresql #триггеры
Вопрос:
У меня проблема с триггером в psql, который должен проверить, существуют ли уже некоторые значения (отправитель, получатель, тема) в таблице, и если они существуют, мне нужно обновить только одно значение (subject = RE: subject) в этой строке, если нет, то мне нужно вставить новую строку.
CREATE OR REPLACE FUNCTION check_theme()
RETURNS TRIGGER
AS $$
DECLARE e BOOLEAN;
BEGIN
e := EXISTS(
SELECT *
FROM message
WHERE sender = NEW.sender
AND reciever = NEW.reciever
AND subject = NEW.subject
);
IF NOT e THEN
INSERT INTO message(sender, reciever, subject, text)
VALUES(NEW.sender, NEW.reciever, NEW.subject, NEW.text);
ELSE
UPDATE message
SET subject = 'Re: ' || NEW.subject
WHERE sender = NEW.sender
AND reciever = NEW.reciever
AND subject = NEW.subject;
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER theme_check
BEFORE INSERT OR UPDATE
ON message
FOR EACH ROW EXECUTE PROCEDURE check_theme();
Итак, после того, как я захочу вставить новую строку, в которой уже есть одинаковые значения для отправителя, получателя и субъекта, триггер попадает в инфинитивный цикл.
Что я делаю не так?
Комментарии:
1.
BEFORE INSERT
Триггер должен просто сказатьIF e THEN NEW.subject = 'Re: ' || NEW.subject;
. Однако я не уверен, чего вы хотите вAFTER UPDATE
случае… Вы действительно хотите, чтобы обновления запускали новые вставки в таблицу?2. Чтобы было понятнее, мне нужно решить эту проблему: реализовать триггер и запустить соответствующую функцию «check_theme», которая для каждой записи в таблице сообщений будет проверять, есть ли уже сообщение от того же отправителя, получателя и с тем же заголовком. Если есть, измените заголовок, чтобы включить префикс «Re:» Пример: Заголовок «Привет» изменится на «Re: Привет», если такие темы уже есть. Если нет, то вам нужно вставить новое сообщение.
Ответ №1:
Через несколько дней я понял, что мои знания о том, как работают триггеры, были неверными.. итак, моя ошибка заключалась в том, что я добавлял функцию INSERT, но вставка будет выполнена в любом случае, если не было сообщения с тем же отправителем, получателем и заголовком.Вот почему я всегда получал инфинитивный цикл. Итак, код, который будет работать, приведен ниже
CREATE OR REPLACE FUNCTION provjera_teme()
RETURNS TRIGGER
AS $$
DECLARE postoji BOOLEAN;
BEGIN
postoji := EXISTS(
SELECT poruka
FROM poruka
WHERE posiljatelj = NEW.posiljatelj
AND primatelj = NEW.primatelj
AND (naslov = NEW.naslov OR naslov LIKE 'Re: ' || NEW.naslov)
);
IF postoji THEN
UPDATE poruka
SET naslov = 'Re: ' || naslov
WHERE posiljatelj = NEW.posiljatelj
AND primatelj = NEW.primatelj
AND naslov = NEW.naslov AND naslov NOT LIKE 'Re%';
RETURN NULL;
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER tema_provjera
BEFORE INSERT
ON poruka
FOR EACH ROW EXECUTE PROCEDURE provjera_teme();