Функция обновления возвращает необновленные записи - PullRequest
0 голосов
/ 23 февраля 2020

У меня есть функция PostgreSQL ниже, чтобы обновить набор записей, и я хочу, чтобы он возвращал тот же список записей после обновления. Прямо сейчас он возвращает список записей до их обновления (flag_read=FALSE в возвращенном наборе). Я знаю, что обновление работает хорошо, потому что когда я выполняю запрос к таблице после выполнения функции, я вижу flag_read=TRUE.

Как я могу изменить функцию, чтобы она возвращала обновленный набор записей?

CREATE OR REPLACE FUNCTION base.mark_all_notifications_as_read()
RETURNS SETOF base.notification AS $$
BEGIN
    RETURN QUERY
    WITH unread_notifications AS (
      UPDATE base.notification
      SET flag_read=TRUE 
      WHERE flag_read=FALSE
      AND created_by_id=base.get_current_user_id()
      RETURNING id
    )
    SELECT * FROM base.notification a
    WHERE a.id IN (SELECT id FROM unread_notifications);
END;
$$ language plpgsql VOLATILE STRICT SECURITY DEFINER;

1 Ответ

0 голосов
/ 23 февраля 2020

Все, что вам нужно, это просто UPDATE..RETURNING *. Бесполезные WITH и SELECT - вот что вызывает проблему.

https://www.postgresql.org/docs/current/queries-with.html:

Под-операторы в WITH выполняются одновременно друг с другом и с основным запросом. Следовательно, при использовании операторов изменения данных в WITH порядок, в котором фактически происходят указанные обновления, непредсказуем. Все операторы выполняются с одним и тем же снимком (см. Главу 13), поэтому они не могут «видеть» влияние друг друга на целевые таблицы. Это смягчает последствия непредсказуемости фактического порядка обновления строк и означает, что данные RETURNING являются единственным способом передачи изменений между различными под-операторами WITH и основным запросом.

РЕДАКТИРОВАТЬ: Добавление полной функции в качестве примера

CREATE OR REPLACE FUNCTION base.mark_all_notifications_as_read()
RETURNS SETOF base.notification AS $$
BEGIN
    RETURN QUERY
    UPDATE base.notification
    SET flag_read=TRUE 
    WHERE flag_read=FALSE
    AND created_by_id=base.get_current_user_id()
    RETURNING *;
END;
$$ language plpgsql VOLATILE STRICT SECURITY DEFINER;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...