6.4. Возврат данных из изменённых строк #
Иногда бывает полезно получать данные из модифицируемых строк в процессе их обработки. Это возможно с использованием предложения RETURNING, которое можно задать для команд INSERT, UPDATE, DELETE и MERGE. Применение RETURNING позволяет обойтись без дополнительного запроса к базе для сбора данных и это особенно ценно, когда как-то иначе трудно получить изменённые строки надёжным образом.
В предложении RETURNING допускается то же содержимое, что и в выходном списке команды SELECT (см. Раздел 7.3). Оно может содержать имена столбцов целевой таблицы команды или значения выражений с этими столбцами. Также часто применяется краткая запись RETURNING *, выбирающая все столбцы целевой таблицы по порядку.
В команде INSERT данные по умолчанию, выдаваемые в RETURNING, образуются из строки в том виде, в каком она была вставлена. Это не очень полезно при простом добавлении, так как в результате будут получены те же данные, что были переданы клиентом. Но это может быть очень удобно при использовании вычисляемых значений по умолчанию. Например, если в таблице есть столбец serial, в котором генерируются уникальные идентификаторы, команда RETURNING может возвратить идентификатор, назначенный новой строке:
CREATE TABLE users (firstname text, lastname text, id serial primary key);
INSERT INTO users (firstname, lastname) VALUES ('Joe', 'Cool') RETURNING id; Предложение RETURNING также очень полезно с INSERT ... SELECT.
В команде UPDATE данные по умолчанию, выдаваемые в RETURNING, образуются новым содержимым изменённой строки. Например:
UPDATE products SET price = price * 1.10 WHERE price <= 99.99 RETURNING name, price AS new_price;
В команде DELETE данные по умолчанию, выдаваемые в RETURNING, образуются содержимым удалённой строки. Например:
DELETE FROM products WHERE obsoletion_date = 'today' RETURNING *;
В команде MERGE RETURNING позволяет получить данные по умолчанию, которые представляют собой содержимое исходной строки плюс содержимое вставленной, изменённой или удалённой целевой строки. Поскольку исходная и целевая строки часто имеют много одинаковых столбцов, указание RETURNING * может привести к появлению большого количества дублирующихся столбцов, поэтому лучше дополнить его, чтобы получить только исходную или целевую строку. Например:
MERGE INTO products p USING new_products n ON p.product_no = n.product_no WHEN NOT MATCHED THEN INSERT VALUES (n.product_no, n.name, n.price) WHEN MATCHED THEN UPDATE SET name = n.name, price = n.price RETURNING p.*;
В каждой из этих команд также можно явно вернуть старое и новое содержимое изменённой строки. Например:
UPDATE products SET price = price * 1.10
WHERE price <= 99.99
RETURNING name, old.price AS old_price, new.price AS new_price,
new.price - old.price AS price_change; В этом примере new.price эквивалентно простому price, но делает смысл более понятным.
Этот синтаксис для возврата старых и новых значений поддерживается в командах INSERT, UPDATE, DELETE и MERGE, но обычно старые значения будут NULL для INSERT, а новые значения будут NULL для DELETE. Однако бывают ситуации, когда это может быть полезно и для этих команд. Например, при INSERT с предложением ON CONFLICT DO UPDATE старые значения будут не NULL для конфликтующих строк. Аналогично, если DELETE преобразуется в UPDATE правилом перезаписи, новые значения могут быть не NULL.
Если для целевой таблицы заданы триггеры (см. Главу 37), в RETURNING выдаются данные из строки, изменённой триггерами. Таким образом, RETURNING часто применяется и для того, чтобы проверить содержимое столбцов, изменяемых триггерами.