hydrugz
@hydrugz
реклама

Как использовать WHERE для конкретного столбца в DO UPDATE?

День добрый.

Есть у меня такой вот франкенштейн
INSERT
    INTO usersdata_mirror
        (user_id, domain, name, in_chats)
    VALUES
        (100, 'username', 'First name', ARRAY[group_id])
ON CONFLICT
    (user_id)
DO UPDATE
    SET
        name = excluded.name,
        domain = excluded.domain,
        in_chats = usersdata_mirror.in_chats || ARRAY[group_id]::int[]
            WHERE
                not(usersdata_mirror.in_chats @> ARRAY[group_id]::int[])


По моей задумке этот код должен записывать данные о пользователе в таблицу и, в случае если идентификатор user_id уже существует - обновлять данные.
Работает как надо, но только с одним подвохом из-за последних 3-х строк (in_chats хранит массив с ID групп, где состоит пользователь):
Данные обновляются только в случае, если пользователь напишет в чате где он ранее не был.
Например.
Сейчас для user_id 1 хранится массив с группами 222, 333 и 444. Но он состоит ещё и в 555, где не написал ни одного сообщения. А name равно Саша.
Позже он переименовался в Васю, но, пока он не напишет в группу 555 - name остаётся Сашей. Хотя он активно общается в других тех группах и запись идет при каждом новом сообщении...
Я так понимаю что данные обновляются только когда срабатывает WHERE NOT для DO UPDATE.
Вот и вопрос, можно ли или как правильно использовать конструкцию WHERE для конкретного столбца in_chats? Или я вообще не туда мыслю? В голове совсем каша уже.

И поделитесь опытом пожалуйста, как вы используете WHERE NOT IN ARRAY в DO UPDATE.
Postgres версии 12.4; работаю с psycopg2. Код для телеграм бота.
  • Вопрос задан
  • 85 просмотров
Решения вопроса 1
Melkij
@Melkij
PostgreSQL DBA
Вас ваше выравнивание запроса путает.
UPDATE tablename
    SET
        name = ?,
        domain = ?,
        in_chats = usersdata_mirror.in_chats || ARRAY[?]::int[]
            WHERE
                not(usersdata_mirror.in_chats @> ARRAY[?]::int[]) and user_id = ?

Что будет делать? Обновлять name при каждом вызове? Нет, конечно.
А почему делающий именно это on conflict должен себя вести иначе? where относится не к полю, а ко всему do update.

Если хотите отдельную логику для поля - то в выражении обновления конкретного поля её и напишите.
in_chats = case when ... then ... else usersdata_mirror.in_chats end
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы