6.4. Retorno dos dados das linhas modificadas #

Às vezes é útil obter dados das linhas modificadas enquanto elas estão sendo manipuladas. Os comandos INSERT, UPDATE, DELETE e MERGE possuem a cláusula opcional RETURNING que permite fazer isto. O uso de RETURNING evita realizar uma consulta adicional ao banco de dados para coletar os dados, sendo particularmente valioso quando, de outra forma, seria difícil identificar as linhas modificadas de forma confiável.

O conteúdo permitido para a cláusula RETURNING é o mesmo da lista de saída do comando SELECT (veja a Seção 7.3). Pode conter nomes de coluna da tabela de destino do comando, ou expressões de valor usando essas colunas. Uma forma abreviada comum é RETURNING *, que seleciona todas as colunas da tabela de destino em ordem.

No comando INSERT, os dados padrão disponíveis para RETURNING são os da linha na forma como foi inserida. Isto não é tão útil em inserções triviais, porque apenas repete os dados fornecidos pelo cliente, mas pode ser muito útil na presença de valores padrão calculados. Por exemplo, ao se usar a coluna serial para fornecer identificadores únicos, RETURNING pode retornar o ID atribuído à nova linha:

CREATE TABLE usuarios (primeiro_nome text, ultimo_nome text, id serial primary key);

INSERT INTO usuarios (primeiro_nome, ultimo_nome) VALUES ('Joe', 'Cool') RETURNING id;

 id
----
  1
(1 linha)

INSERT 0 1

A cláusula RETURNING também é muito útil com INSERT ... SELECT.

No comando UPDATE, os dados disponíveis para RETURNING são os do novo conteúdo da linha modificada. Por exemplo:

UPDATE produtos SET preco = preco * 1.10
  WHERE preco <= 99.99
  RETURNING nome, preco AS novo_preco;

  nome  | novo_preco
--------+------------
 Queijo |    10.9890
(1 linha)

UPDATE 1

No comando DELETE, os dados padrão disponíveis para RETURNING são os do conteúdo da linha excluída. Por exemplo:

DELETE FROM produtos
  WHERE nome = 'Queijo'
  RETURNING *;

 num_produto |  nome  |  preco
-------------+--------+---------
           1 | Queijo | 10.9890
(1 linha)

DELETE 1

No comando MERGE, os dados padrão disponíveis para RETURNING são o conteúdo da linha de origem mais o conteúdo da linha inserida, atualizada ou excluída. Como é muito comum que as linhas de origem e de destino tenham muitas colunas idênticas, especificar RETURNING * pode produzir muitas colunas duplicadas, portanto geralmente é mais útil qualificá-lo para que retorne apenas a linha de origem ou de destino. Por exemplo:

INSERT INTO produtos VALUES (1, 'Queijo', 9.99);
INSERT INTO novos_produtos VALUES (1, 'Leite', 4.99);
INSERT INTO novos_produtos VALUES (2, 'Açúcar', 3.99);

MERGE INTO produtos p USING novos_produtos n ON p.num_produto = n.num_produto
  WHEN NOT MATCHED THEN INSERT VALUES (n.num_produto, n.nome, n.preco)
  WHEN MATCHED THEN UPDATE SET nome = n.nome, preco = n.preco
  RETURNING p.*;

 num_produto |  nome  | preco
-------------+--------+-------
           1 | Leite  |  4.99
           2 | Açúcar |  3.99
(2 linhas)

MERGE 2

Em cada um destes comandos, também é possível retornar explicitamente o conteúdo antigo e o novo da linha modificada. Por exemplo:

UPDATE produtos SET preco = preco * 1.10
  WHERE preco <= 99.99
  RETURNING nome, old.preco AS preco_antigo, new.preco AS preco_novo,
            new.preco - old.preco AS mudanca_preco;

  nome  | preco_antigo | preco_novo | mudanca_preco
--------+--------------+------------+---------------
 Leite  |         4.99 |     5.4890 |        0.4990
 Açúcar |         3.99 |     4.3890 |        0.3990
(2 linhas)

UPDATE 2

No exemplo acima, escrever new.preco é a mesma coisa que escrever apenas preco, mas isto torna o significado mais claro.

Esta sintaxe para retornar valores antigos e novos está disponível nos comandos INSERT, UPDATE, DELETE e MERGE, mas normalmente os valores antigos serão NULL para o comando INSERT, e os novos valores serão NULL para o comando DELETE. Entretanto, existem situações em que new. ainda pode ser útil para estes comandos. Por exemplo, em um comando INSERT contendo a cláusula ON CONFLICT DO UPDATE, os valores antigos serão não-NULL para as linhas conflitantes. De forma semelhante, se um comando DELETE se tornar um comando UPDATE devido a uma regra de reescrita, os novos valores serão não-NULL.

Se houver gatilhos (veja o Capítulo 37) na tabela de destino, os dados disponíveis para RETURNING serão os da linha modificada pelos gatilhos. Assim, inspecionar colunas computadas por gatilhos é outro caso de uso comum para RETURNING.