зеркало из
				https://github.com/iharh/notes.git
				synced 2025-10-31 21:56:08 +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 и пользуемся!
 | 
