зеркало из
https://github.com/iharh/notes.git
synced 2025-10-29 20:56:06 +02:00
62 строки
3.7 KiB
Plaintext
62 строки
3.7 KiB
Plaintext
Обращение к предыдущим (OLD) и к текущим (NEW) значениям в предложении RETURNING в PostgreSQL 18.
|
|
|
|
Всем привет!
|
|
|
|
Помимо таких ключевых функций в PostgreSQL 18, как асинхронный ввод-вывод и поддержка UUIDv7, мы получили вот такое небольшое, но приятное улучшение.
|
|
|
|
В этой версии добавлена возможность обращаться как к предыдущим (OLD), так и к текущим (NEW) значениям в предложении RETURNING для команд INSERT, UPDATE, DELETE и MERGE. Суть в том, что теперь доступны два синонима OLD и NEW, с помощью которых мы можем возвращать старые и новые значения в предложении RETURNING.
|
|
|
|
Это не революционное изменение, как асинхронный ввод-вывод, но это одна из тех небольших функций, которая оказывается просто неоценимой в определённых ситуациях.
|
|
|
|
Простая демонстрация с UPDATE для получения всех старых и новых значений:
|
|
|
|
UPDATE fruit
|
|
SET quantity = 300
|
|
WHERE item = 'Apples'
|
|
RETURNING OLD.*, NEW.*;
|
|
|
|
Вывод:
|
|
|
|
id|item|quantity|id|item|quantity
|
|
——+—-——+————————+——+———+——————
|
|
5|Apples| 200 | 5| Apples |300
|
|
(1 row)
|
|
|
|
Получается очень просто, удобно и наглядно! Все как мы любим! ☺️
|
|
|
|
Вот еще пример.
|
|
|
|
Допустим, мы выполняем операцию UPSERT (INSERT ... ON CONFLICT ... DO UPDATE) и хотим определить, была ли строка, возвращённая RETURNING, новой вставленной строкой или существующей обновлённой строкой. Это было возможно и раньше, но полагалось на неинтуитивную проверку xmax = 0:
|
|
|
|
INSERT INTO webhook (
|
|
id,
|
|
data
|
|
) VALUES (
|
|
@id,
|
|
@data
|
|
)
|
|
ON CONFLICT (id)
|
|
DO UPDATE SET id = webhook.id
|
|
RETURNING webhook.*,
|
|
(xmax = 0) AS is_new;
|
|
|
|
Этот оператор полагается на то, что xmax устанавливается в ноль для новой вставки, что является особенностью реализации блокировок в PostgreSQL. Это работает, но не является гарантированной частью API и потенциально может измениться в любой момент.
|
|
|
|
В PostgreSQL 18 мы можем переписать приведённый выше код так, чтобы он был более понятным и не зависел от деталей реализации. Это также просто - достаточно проверить, является ли OLD значением NULL в предложении RETURNING:
|
|
|
|
INSERT INTO webhook (
|
|
id,
|
|
data
|
|
) VALUES (
|
|
@id,
|
|
@data
|
|
)
|
|
ON CONFLICT (id)
|
|
DO UPDATE SET id = webhook.id
|
|
RETURNING webhook.*,
|
|
(OLD IS NULL)::boolean AS is_new;
|
|
|
|
Доступ к OLD и NEW, без сомнения, найдёт множество других полезных применений, но этот пример позволяет нам сразу же улучшить код, написанный до 18-й версии.
|
|
|
|
Переходим на PostgreSQL 18 и пользуемся!
|