2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2

6.4. 返回已修改行的 Dati #

有时,在操作行时获取已修改行的数据非常有用。INSERTUPDATEDELETEMERGE 命令都包含可选的 RETURNING 子句,支持此功能。使用 RETURNING 可以避免执行额外的数据库查询来收集数据,当否则难以可靠地识别已修改的行时,尤其有价值。

RETURNING 子句允许的内容与 SELECT 命令的输出列表相同(参见 Section 7.3)。它可以包含命令目标表的列名,或使用这些列的值表达式。一个常见的简写是 RETURNING *,它按顺序选择目标表的所有列。

INSERT 中,RETURNING 可用的默认数据是插入时的行。这在简单的插入操作中不太有用,因为它只会重复客户端提供的数据。但当依赖于计算出的默认值时,它可能非常方便。例如,在使用 serial 列提供唯一标识符时,RETURNING 可以返回分配给新行的 ID。

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 相同,但它使含义更清晰。

这种返回旧值和新值的语法在 INSERTUPDATEDELETEMERGE 命令中可用,但对于 INSERT,旧值通常是 NULL,对于 DELETE,新值通常是 NULL。但是,在某些情况下,对于这些命令它仍然有用。例如,在带有 ON CONFLICT DO UPDATE 子句的 INSERT 中,对于冲突的行,旧值将是非 NULL 的。类似地,如果 DELETE 通过 重写规则 变成了 UPDATE,则新值可能是 NULL

如果目标表上有触发器(参见 Chapter 37),则 RETURNING 可用的数据是经触发器修改后的行。因此,检查由触发器计算的列是 RETURNING 的另一个常见用例。

提交更正

如果您在文档中发现任何不正确、与您对特定功能的体验不符或需要进一步澄清的内容,请使用 此表单 报告文档问题。