受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

6.4. 从被修改的行中返回数据 #

有时候,在修改行的同时取得这些行中的数据会很有用。 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 命令,但通常旧值会是 NULL(对于 INSERT),而新值会是 NULL(对于 DELETE)。不过,在某些情况下,它对这些命令仍然有用。例如,在 INSERT 中,如果带有 ON CONFLICT DO UPDATE 子句,那么对于发生冲突的行,旧值将是非 NULL 的。类似地,如果某个 DELETE 被改写成 UPDATE(通过 重写规则),新值也可能是非 NULL 的。

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

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。