L
L
Lesha2021-02-08 12:42:38
PostgreSQL
Lesha, 2021-02-08 12:42:38

How to use WHERE on specific column in DO UPDATE?

Good afternoon.

I have this Frankenstein

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[])


According to my idea, this code should write user data to the table and, if the user_id already exists, update the data.
Works as it should, but only with one catch because of the last 3 lines (in_chats stores an array with the group IDs where the user is):
The data is updated only if the user writes in a chat where he was not previously.
For example.
Now for user_id 1, an array is stored with groups 222, 333 and 444. But it also consists of 555, where he did not write a single message. And name is Sasha.
Later he changed his name to Vasya, but until he writes to the 555 group, the name remains Sasha. Although he actively communicates in other those groups and the recording goes on with each new message ...
I so understand that the data is updated only when WHERE NOT for DO UPDATE works.
So the question is, is it possible or how to correctly use the WHERE clause for a specific in_chats column? Or am I not thinking there at all? My head is already a mess.

And share your experience please, how do you use WHERE NOT IN ARRAY in DO UPDATE.
Postgres version 12.4; I work with psycopg2. Telegram bot code.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Melkij, 2021-02-08
@hydrugz

Your alignment of request confuses you.

UPDATE tablename
    SET
        name = ?,
        domain = ?,
        in_chats = usersdata_mirror.in_chats || ARRAY[?]::int[]
            WHERE
                not(usersdata_mirror.in_chats @> ARRAY[?]::int[]) and user_id = ?

What will do? Update name on every call? Of course not.
And why should the one doing exactly this on conflict behave differently? where does not refer to a field, but to everything do update.
If you want a separate logic for a field, then write it in the update expression of a specific field.
in_chats = case when ... then ... else usersdata_mirror.in_chats end

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question