Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Не работает (WITH + UPSERT + UPDATE) / 6 сообщений из 6, страница 1 из 1
05.01.2021, 02:47
    #40033537
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает (WITH + UPSERT + UPDATE)
Код: sql
1.
2.
3.
4.
WITH upsert AS (
   INSERT INTO test (id, name) VALUES (2,'old name'::text)
   ON CONFLICT (id) DO UPDATE SET id = EXCLUDED.id, name = EXCLUDED.name WHERE test.id = EXCLUDED.id RETURNING id
) UPDATE test SET name = 'new name' FROM upsert WHERE test.id = upsert.id;


Здесь вложенный в WITH запрос работает корректно (обновляет существующую запись с id = 2 и возвращает эту запись главному запросу).
Главный запрос у полученной записи с id = 2 должен изменить name . Но главный запрос ничего не меняет.

Если условие (test.id = upsert.id) заменить на (test.id <> upsert.id), то главный запрос меняет name у всех записей, кроме id = 2 .
Т.е. условие (test.id = upsert.id) срабатывет, но запись ( name ) не меняется. Бред какой-то...

P.S . Очевидно, что если два запроса выполнить отдельно, проблем не будет. Но в случае с WITH происходит какая-то петрушка...
...
Рейтинг: 0 / 0
05.01.2021, 10:02
    #40033550
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает (WITH + UPSERT + UPDATE)
Cyrax_02,

Как обычно внимательно читаем документацию в части https://www.postgresql.org/docs/13/queries-with.html#QUERIES-WITH-MODIFYING
Особенно предпоследний абзац звучащий как:

документацияTrying to update the same row twice in a single statement is not supported. Only one of the modifications takes place, but it is not easy (and sometimes not possible) to reliably predict which one. This also applies to deleting a row that was already updated in the same statement: only the update is performed. Therefore you should generally avoid trying to modify a single row twice in a single statement. In particular avoid writing WITH sub-statements that could affect the same rows changed by the main statement or a sibling sub-statement. The effects of such a statement will not be predictable.

почему так - написано выше по тексту.

В общем результат unspecified и так делать не надо.



--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
05.01.2021, 14:28
    #40033614
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает (WITH + UPSERT + UPDATE)
Код: sql
1.
2.
3.
4.
5.
6.
UPDATE test SET name = 'new name' FROM (
   INSERT INTO test (id, name) VALUES (2,'old name'::text)
   ON CONFLICT (id) DO UPDATE SET id = EXCLUDED.id, name = EXCLUDED.name WHERE test.id = EXCLUDED.id RETURNING id
) upsert WHERE test.id = upsert.id;

SQL Error [42601]: ОШИБКА: ошибка синтаксиса (примерное положение: "INTO")


Тогда получается, что одним запросом никаким способом невозможно выполнить последовательные UPSERT + UPDATE на одной и той же строке ?

Maxim BogukОсобенно предпоследний абзац звучащий как:Этот абзац я читал. Только вот под оператором я понимал одну несоставную команду (в данном случае UPSERT или UPDATE).
Как оказалось, речь идёт в т.ч. и о составных командах.
...
Рейтинг: 0 / 0
05.01.2021, 17:53
    #40033667
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает (WITH + UPSERT + UPDATE)
Cyrax_02
Код: sql
1.
2.
3.
4.
5.
6.
UPDATE test SET name = 'new name' FROM (
   INSERT INTO test (id, name) VALUES (2,'old name'::text)
   ON CONFLICT (id) DO UPDATE SET id = EXCLUDED.id, name = EXCLUDED.name WHERE test.id = EXCLUDED.id RETURNING id
) upsert WHERE test.id = upsert.id;

SQL Error [42601]: ОШИБКА: ошибка синтаксиса (примерное положение: "INTO")


Тогда получается, что одним запросом никаким способом невозможно выполнить последовательные UPSERT + UPDATE на одной и той же строке ?

Maxim BogukОсобенно предпоследний абзац звучащий как:
Этот абзац я читал. Только вот под оператором я понимал одну несоставную команду (в данном случае UPSERT или UPDATE).
Как оказалось, речь идёт в т.ч. и о составных командах.

Одним запросом - нельзя без использования хранимых процедур.

WITH это одна монолитная команда а не составная... составная команда это когда несколько sql запросов в одной строке отправляются через ; .
Никогда не стоит смешивать в голове WITH c несколькими блоками и несколько sql комманд через ; - это очень разные вещи и работают по разному.

PS: не могу понять в каком реальном use case вам такая странная задача понадобилась. Обычно подобные вещи через BEFORE триггер решаются.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
05.01.2021, 19:50
    #40033685
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает (WITH + UPSERT + UPDATE)
Maxim BogukWITH это одна монолитная команда а не составная... Под " составной командой " в предыдущем посте я имел ввиду многоблочную команду с WITH , а не " запрос; запрос ; ...".

Maxim BogukPS: не могу понять в каком реальном use case вам такая странная задача понадобилась. Обычно подобные вещи через BEFORE триггер решаются. Подобные - это какие ? Выполнение BEFORE-триггером операции INSERT или UPDATE в зависимости от значений полей (для этого есть UPSERT) ?
Сабжевый пример с точки зрения логики абсолютно бессмыслен (упрощённая форма реального запроса, воспроизводящая проблему).
...
Рейтинг: 0 / 0
05.01.2021, 20:40
    #40033691
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Не работает (WITH + UPSERT + UPDATE)
Cyrax_02

Maxim BogukPS: не могу понять в каком реальном use case вам такая странная задача понадобилась. Обычно подобные вещи через BEFORE триггер решаются.
Подобные - это какие ? Выполнение BEFORE-триггером операции INSERT или UPDATE в зависимости от значений полей (для этого есть UPSERT) ?
Сабжевый пример с точки зрения логики абсолютно бессмыслен (упрощённая форма реального запроса, воспроизводящая проблему).

такие это когда надо сложную логику реализовать перед тем как менять что то в таблице
в вашем случае это "выполнить последовательные UPSERT + UPDATE надо одной строкой в пределах 1 запроса"


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Не работает (WITH + UPSERT + UPDATE) / 6 сообщений из 6, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]