Partilhar via


Cláusula OUTPUT (Transact-SQL)

Aplica-se a:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceBase de dados SQL no Microsoft Fabric

Retorna informações de, ou expressões baseadas em, cada linha afetada por um INSERT, UPDATE, DELETEou MERGE instrução. Esses resultados podem ser retornados ao aplicativo de processamento para uso em coisas como mensagens de confirmação, arquivamento e outros requisitos do aplicativo. Os resultados também podem ser inseridos em uma tabela ou variável de tabela. Além disso, você pode capturar os resultados de uma OUTPUT cláusula em uma instrução , , INSERTUPDATEou DELETE aninhada MERGEe inserir esses resultados em uma tabela ou exibição de destino.

Note

Uma UPDATEinstrução , , ou INSERT que tenha uma DELETE cláusula retornará OUTPUTlinhas para o cliente, mesmo que a instrução encontre erros e seja revertida. O resultado não deve ser usado se ocorrer algum erro ao executar a instrução.

Utilizado em:

Transact-SQL convenções de sintaxe

Syntax

<OUTPUT_CLAUSE> ::=
{
    [ OUTPUT <dml_select_list> INTO { @table_variable | output_table } [ ( column_list ) ] ]
    [ OUTPUT <dml_select_list> ]
}
<dml_select_list> ::=
{ <column_name> | scalar_expression } [ [ AS ] column_alias_identifier ]
    [ , ...n ]

<column_name> ::=
{ DELETED | INSERTED | from_table_name } . { * | column_name }
    | $action

Arguments

@table_variable

Especifica uma variável de tabela na qual as linhas retornadas são inseridas em vez de serem retornadas ao chamador. @table_variable deve ser declarado antes da INSERTUPDATE, , DELETEou MERGE declaração.

Se column_list não for especificado, a variável de tabela deverá ter o mesmo número de colunas que o OUTPUT conjunto de resultados. As exceções são a identidade e as colunas computadas, que devem ser ignoradas. Se column_list for especificado, todas as colunas omitidas deverão permitir valores nulos ou ter valores padrão atribuídos a elas.

Para obter mais informações sobre variáveis de tabela , consulte tabela.

output_table

Especifica uma tabela na qual as linhas retornadas são inseridas em vez de serem retornadas ao chamador. output_table pode ser uma tabela temporária.

Se column_list não for especificado, a tabela deverá ter o mesmo número de colunas que o OUTPUT conjunto de resultados. As exceções são a identidade e as colunas computadas, que devem ser ignoradas. Se column_list for especificado, todas as colunas omitidas deverão permitir valores nulos ou ter valores padrão atribuídos a elas.

output_table não podem:

  • Ter ativado gatilhos definidos nele.
  • Participe de ambos os lados de uma FOREIGN KEY restrição.
  • Ter CHECK restrições ou regras habilitadas.

column_list

Uma lista opcional de nomes de colunas na tabela de destino da INTO cláusula. É análogo à lista de colunas permitida na instrução INSERT .

scalar_expression

Qualquer combinação de símbolos e operadores que seja avaliada como um único valor. Funções agregadas não são permitidas no scalar_expression.

Qualquer referência a colunas na tabela que está sendo modificada deve ser qualificada com o prefixo INSERTED ou DELETED .

column_alias_identifier

Um nome alternativo usado para fazer referência ao nome da coluna.

SUPRIMIDO

Um prefixo de coluna que especifica o valor excluído pela operação de atualização ou exclusão e quaisquer valores existentes que não sejam alterados com a operação atual. As colunas prefixadas com DELETED refletem o valor antes que a UPDATEinstrução , DELETEou MERGE seja concluída.

DELETED não pode ser usado com a OUTPUT cláusula da INSERT declaração.

INSERIDO

Um prefixo de coluna que especifica o valor adicionado pela operação de inserção ou atualização e quaisquer valores existentes que não sejam alterados com a operação atual. As colunas prefixadas com INSERTED refletem o valor depois que a UPDATEinstrução , INSERTou MERGE é concluída, mas antes que os gatilhos sejam executados.

INSERTED não pode ser usado com a OUTPUT cláusula da DELETE declaração.

from_table_name

Um prefixo FROM de coluna que especifica uma tabela incluída na cláusula de uma DELETEinstrução , UPDATEou MERGE que é usada para especificar as linhas a serem atualizadas ou excluídas.

Se a tabela que está sendo modificada também for especificada na FROM cláusula, qualquer referência a colunas nessa tabela deverá ser qualificada com o prefixo INSERTED ou DELETED .

*

O asterisco (*) especifica que todas as colunas afetadas pela ação excluir, inserir ou atualizar são retornadas na ordem em que existem na tabela.

Por exemplo, OUTPUT DELETED.* na instrução a seguir DELETE retorna todas as colunas excluídas da ShoppingCartItem tabela:

DELETE Sales.ShoppingCartItem
    OUTPUT DELETED.*;

column_name

Uma referência explícita de coluna. Qualquer referência à tabela que está sendo modificada deve ser corretamente qualificada pelo prefixo ou pelo prefixo INSERTEDDELETED , conforme apropriado, por exemplo: INSERTED.<column_name>.

$action

Disponível apenas para a MERGE declaração. Especifica uma coluna do tipo nvarchar(10) na OUTPUT cláusula de uma MERGE instrução que retorna um dos três valores para cada linha: INSERT, UPDATEou , de DELETEacordo com a ação executada nessa linha.

Remarks

A OUTPUT <dml_select_list> cláusula e a OUTPUT <dml_select_list> INTO { @table_variable | output_table } cláusula podem ser definidas em um único INSERT, UPDATE, DELETE, ou MERGE declaração.

Note

Salvo indicação em contrário, as referências à OUTPUT cláusula referem-se tanto à cláusula OUTPUT como OUTPUT INTO à cláusula.

A OUTPUT cláusula pode ser útil para recuperar o valor da identidade ou colunas computadas após uma INSERT operação ou UPDATE .

Quando uma coluna computada é incluída no <dml_select_list>, a coluna correspondente na tabela de saída ou variável de tabela não é uma coluna calculada. Os valores na nova coluna são os valores que foram calculados no momento em que a instrução foi executada.

Não é garantido que a ordem em que as alterações são aplicadas à tabela e a ordem em que as linhas são inseridas na tabela de saída ou na variável da tabela.

Se parâmetros ou variáveis forem modificados como parte de uma UPDATE instrução, a OUTPUT cláusula sempre retornará o valor do parâmetro ou variável como era antes da instrução executada em vez do valor modificado.

Você pode usar OUTPUT com uma UPDATE instrução or posicionada DELETE em um cursor que usa WHERE CURRENT OF sintaxe.

A OUTPUT cláusula não é suportada nas seguintes declarações:

  • Instruções DML que fazem referência a exibições particionadas locais, exibições particionadas distribuídas ou tabelas remotas.

  • INSERT declarações que contenham uma EXECUTE declaração.

  • Predicados de texto completo não são permitidos OUTPUT na cláusula quando o nível de compatibilidade do banco de dados é definido como 100.

  • A OUTPUT INTO cláusula não pode ser usada para inserir em um modo de exibição ou função de conjunto de linhas.

  • Uma função definida pelo usuário não pode ser criada se contiver uma OUTPUT INTO cláusula que tenha uma tabela como destino.

Para evitar um comportamento não determinístico, a OUTPUT cláusula não pode conter as seguintes referências:

  • Subconsultas ou funções definidas pelo usuário que executam o acesso aos dados do usuário ou do sistema, ou presume-se que executem esse acesso. Presume-se que as funções definidas pelo usuário executem o acesso aos dados se não estiverem ligadas ao esquema.

  • Uma coluna de um modo de exibição ou função com valor de tabela embutido quando essa coluna é definida por um dos seguintes métodos:

    • Uma subconsulta.

    • Uma função definida pelo usuário que executa o acesso aos dados do usuário ou do sistema, ou presume-se que execute esse acesso.

    • Uma coluna computada que contém uma função definida pelo usuário que executa o acesso aos dados do usuário ou do sistema em sua definição.

    Quando o SQL Server deteta essa coluna na cláusula, o OUTPUT erro 4186 é gerado.

Inserir dados retornados de uma cláusula OUTPUT em uma tabela

Ao capturar os resultados de uma OUTPUT cláusula em uma instrução , , INSERTUPDATEou DELETE aninhada MERGEe inserir esses resultados em uma tabela de destino, lembre-se das seguintes informações:

  • Toda a operação é atómica. A instrução e a INSERT instrução DML aninhada que contém a OUTPUT cláusula execute, ou a instrução inteira falhará.

  • As seguintes restrições aplicam-se ao destino da instrução externa INSERT :

    • O destino não pode ser uma tabela, exibição ou expressão de tabela comum remota.

    • O destino não pode ter uma FOREIGN KEY restrição ou ser referenciado por uma FOREIGN KEY restrição.

    • Os gatilhos não podem ser definidos no destino.

    • O destino não pode participar da replicação de mesclagem ou de assinaturas atualizáveis para replicação transacional.

  • As seguintes restrições se aplicam à instrução DML aninhada:

    • O destino não pode ser uma tabela remota ou uma vista particionada.

    • A fonte em si não pode conter uma <dml_table_source> cláusula.

  • A OUTPUT INTO cláusula não é suportada em INSERT instruções que contenham uma <dml_table_source> cláusula.

  • @@ROWCOUNT Retorna as linhas inseridas somente pela instrução Outer INSERT .

  • @@IDENTITY, SCOPE_IDENTITYe IDENT_CURRENT retornam valores de identidade gerados somente pela instrução DML aninhada, e não valores gerados pela instrução externa INSERT .

  • As notificações de consulta tratam a instrução como uma única entidade, e o tipo de qualquer mensagem criada é o tipo da DML aninhada, mesmo que a alteração significativa seja da própria instrução externa INSERT .

  • <dml_table_source> Na cláusula, as SELECT cláusulas e WHERE não podem incluir subconsultas, funções agregadas, funções de classificação, predicados de texto completo, funções definidas pelo usuário que executam acesso a dados ou a TEXTPTR() função.

Parallelism

Uma OUTPUT cláusula que retorna resultados para o cliente, ou variável de tabela, sempre usa um plano serial.

No contexto de um banco de dados definido para o nível de compatibilidade 130 ou superior, se uma INSERT...SELECT operação usa uma WITH (TABLOCK) dica para a SELECT instrução e também usa OUTPUT...INTO para inserir em uma tabela temporária ou de usuário, a tabela de destino para o é elegível para paralelismo, INSERT...SELECT dependendo do custo da subárvore. A tabela de destino mencionada OUTPUT INTO na cláusula não é elegível para paralelismo.

Triggers

As colunas retornadas refletem os dados após a conclusão da OUTPUTINSERTinstrução , UPDATEou DELETE , mas antes que os gatilhos sejam executados.

Para INSTEAD OF gatilhos, os resultados retornados são gerados como se o INSERT, UPDATEou DELETE tivesse realmente ocorrido, mesmo que nenhuma modificação ocorra como resultado da operação de gatilho. Se uma instrução que inclui uma OUTPUT cláusula for usada dentro do corpo de um gatilho, os aliases de tabela deverão ser usados para fazer referência às tabelas inseridas e excluídas do gatilho para evitar a duplicação de referências de coluna com as tabelas e INSERTED associadas ao DELETEDOUTPUT.

Se a OUTPUT cláusula for especificada sem especificar também a INTO palavra-chave, o destino da operação DML não poderá ter nenhum gatilho ativado definido nela para determinada ação DML. Por exemplo, se a OUTPUT cláusula for definida em uma UPDATE instrução, a tabela de destino não poderá ter nenhum gatilho habilitado UPDATE .

Se a sp_configure opção não permitir resultados de gatilhos for definida, uma OUTPUT cláusula sem cláusula INTO fará com que a instrução falhe quando for invocada de dentro de um gatilho.

Tipos de dados

A OUTPUT cláusula suporta os tipos de dados de objeto grande: nvarchar(max), varchar(max), varbinary(max), text, ntext, image e xml. Quando você usa a .WRITE cláusula na UPDATE instrução para modificar uma coluna nvarchar(max), varchar(max) ou varbinary(max), as imagens completas antes e depois dos valores são retornadas se forem referenciadas. A TEXTPTR() função não pode aparecer como parte de uma expressão em uma coluna de texto, ntext ou imagem na OUTPUT cláusula.

Queues

Você pode usar OUTPUT em aplicativos que usam tabelas como filas ou para manter conjuntos de resultados intermediários. Ou seja, o aplicativo está constantemente adicionando ou removendo linhas da tabela. O exemplo a seguir usa a OUTPUT cláusula em uma DELETE instrução para retornar a linha excluída para o aplicativo de chamada.

USE AdventureWorks2022;
GO

DELETE TOP(1) dbo.DatabaseLog WITH (READPAST)
OUTPUT DELETED.*
WHERE DatabaseLogID = 7;
GO

Este exemplo remove uma linha de uma tabela usada como fila e retorna os valores excluídos para o aplicativo de processamento em uma única ação. Outras semânticas também podem ser implementadas, como o uso de uma tabela para implementar uma pilha. No entanto, o SQL Server não garante a ordem na qual as linhas são processadas e retornadas pelas instruções DML usando a OUTPUT cláusula. Cabe ao aplicativo incluir uma cláusula apropriada WHERE que possa garantir a semântica desejada ou entender que, quando várias linhas podem se qualificar para a operação DML, não há ordem garantida. O exemplo a seguir usa uma subconsulta e assume que a DatabaseLogID exclusividade é uma característica da coluna para implementar a semântica de ordenação desejada.

USE tempdb;
GO

CREATE TABLE dbo.table1
(
    id INT,
    employee VARCHAR(32)
);
GO

INSERT INTO dbo.table1
VALUES (1, 'Fred'),
    (2, 'Tom'),
    (3, 'Sally'),
    (4, 'Alice');
GO

DECLARE @MyTableVar TABLE (
    id INT,
    employee VARCHAR(32)
);

PRINT 'table1, before delete';

SELECT *
FROM dbo.table1;

DELETE
FROM dbo.table1
OUTPUT DELETED.*
INTO @MyTableVar
WHERE id = 4
    OR id = 2;

PRINT 'table1, after delete';

SELECT *
FROM dbo.table1;

PRINT '@MyTableVar, after delete';

SELECT *
FROM @MyTableVar;

DROP TABLE dbo.table1;

Eis os resultados:

table1, before delete
id          employee
----------- ------------------------------
1           Fred
2           Tom
3           Sally
4           Alice

table1, after delete
id          employee
----------- ------------------------------
1           Fred
3           Sally

@MyTableVar, after delete
id          employee
----------- ------------------------------
2           Tom
4           Alice

Note

Use a dica READPAST de tabela e UPDATE instruções se DELETE o seu cenário permitir que vários aplicativos executem uma leitura destrutiva de uma tabela. Isso evita problemas de bloqueio que podem surgir se outro aplicativo já estiver lendo o primeiro registro de qualificação na tabela.

Permissions

SELECT As permissões são necessárias em todas as colunas recuperadas ou <dml_select_list> usadas no <scalar_expression>.

INSERT As permissões são necessárias em todas as tabelas especificadas em <output_table>.

Examples

Os exemplos de código neste artigo usam o banco de dados de exemplo AdventureWorks2025 ou AdventureWorksDW2025, que pode ser descarregado da página inicial de Exemplos e Projetos da Comunidade do Microsoft SQL Server.

A. Use OUTPUT INTO com uma instrução INSERT

O exemplo a seguir insere uma linha na ScrapReason tabela e usa a OUTPUT cláusula para retornar os resultados da instrução para a @MyTableVar variável table. Como a ScrapReasonID coluna é definida com uma propriedade IDENTITY, um valor não é especificado na INSERT instrução dessa coluna. No entanto, o valor gerado pelo Mecanismo de Banco de Dados para essa coluna é retornado na OUTPUT cláusula na coluna INSERTED.ScrapReasonID.

USE AdventureWorks2022;
GO

DECLARE @MyTableVar TABLE (
    NewScrapReasonID SMALLINT,
    Name VARCHAR(50),
    ModifiedDate DATETIME
);

INSERT Production.ScrapReason
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
        INTO @MyTableVar
VALUES (N'Operator error', GETDATE());

--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason;
GO

B. Usar OUTPUT com uma instrução DELETE

O exemplo a seguir exclui todas as linhas da ShoppingCartItem tabela. A cláusula OUTPUT DELETED.* especifica que os DELETE resultados da instrução, ou seja, todas as colunas nas linhas excluídas, são retornados para o aplicativo de chamada. A SELECT instrução a seguir verifica os resultados da operação de exclusão na ShoppingCartItem tabela.

USE AdventureWorks2022;
GO

DELETE Sales.ShoppingCartItem
OUTPUT DELETED.*
WHERE ShoppingCartID = 20621;

--Verify the rows in the table matching the WHERE clause have been deleted.
SELECT COUNT(*) AS [Rows in Table] FROM Sales.ShoppingCartItem WHERE ShoppingCartID = 20621;
GO

C. Use OUTPUT INTO com uma instrução UPDATE

O exemplo a seguir atualiza a VacationHours coluna na Employee tabela em 25% para as primeiras 10 linhas. A OUTPUT cláusula retorna o VacationHours valor que existe antes de aplicar a UPDATE instrução na coluna DELETED.VacationHourse o valor atualizado na coluna INSERTED.VacationHours para a @MyTableVar variável de tabela.

Seguem-se duas SELECT instruções que retornam os valores e @MyTableVar os resultados da operação de atualização na Employee tabela.

USE AdventureWorks2022;
GO

DECLARE @MyTableVar TABLE (
    EmpID INT NOT NULL,
    OldVacationHours INT,
    NewVacationHours INT,
    ModifiedDate DATETIME);

UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25,
    ModifiedDate = GETDATE()
OUTPUT INSERTED.BusinessEntityID,
       DELETED.VacationHours,
       INSERTED.VacationHours,
       INSERTED.ModifiedDate
INTO @MyTableVar;

--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM @MyTableVar;
GO
--Display the result set of the table.
SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO

D. Use OUTPUT INTO para retornar uma expressão

O exemplo a seguir se baseia no exemplo C definindo uma expressão na OUTPUT cláusula como a diferença entre o valor atualizado VacationHours e o VacationHours valor antes da aplicação da atualização. O valor desta expressão é retornado para a @MyTableVar variável de tabela na coluna VacationHoursDifference.

USE AdventureWorks2022;
GO

DECLARE @MyTableVar TABLE (
    EmpID INT NOT NULL,
    OldVacationHours INT,
    NewVacationHours INT,
    VacationHoursDifference INT,
    ModifiedDate DATETIME);

UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25,
    ModifiedDate = GETDATE()
OUTPUT INSERTED.BusinessEntityID,
       DELETED.VacationHours,
       INSERTED.VacationHours,
       INSERTED.VacationHours - DELETED.VacationHours,
       INSERTED.ModifiedDate
INTO @MyTableVar;

--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours,
    VacationHoursDifference, ModifiedDate
FROM @MyTableVar;
GO
SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO

E. Use OUTPUT INTO com from_table_name em uma instrução UPDATE

O exemplo a seguir atualiza a ScrapReasonIDWorkOrder coluna na tabela para todas as ordens de serviço com um especificado ProductID e ScrapReasonID. A OUTPUT INTO cláusula retorna valores da tabela que está sendo atualizada (WorkOrder) e também da Product tabela. A Product tabela é usada na FROM cláusula para especificar as linhas a serem atualizadas. Como a tabela tem um WorkOrder gatilho AFTER UPDATE definido, a INTO palavra-chave é necessária.

USE AdventureWorks2022;
GO

DECLARE @MyTestVar TABLE (
    OldScrapReasonID INT NOT NULL,
    NewScrapReasonID INT NOT NULL,
    WorkOrderID INT NOT NULL,
    ProductID INT NOT NULL,
    ProductName NVARCHAR(50)NOT NULL);

UPDATE Production.WorkOrder
SET ScrapReasonID = 4
OUTPUT DELETED.ScrapReasonID,
       INSERTED.ScrapReasonID,
       INSERTED.WorkOrderID,
       INSERTED.ProductID,
       p.Name
    INTO @MyTestVar
FROM Production.WorkOrder AS wo
    INNER JOIN Production.Product AS p
    ON wo.ProductID = p.ProductID
    AND wo.ScrapReasonID= 16
    AND p.ProductID = 733;

SELECT OldScrapReasonID, NewScrapReasonID, WorkOrderID,
    ProductID, ProductName
FROM @MyTestVar;
GO

F. Use OUTPUT INTO com from_table_name em uma instrução DELETE

O exemplo a seguir exclui linhas na ProductProductPhoto tabela com base nos critérios de pesquisa definidos na FROM cláusula da DELETE instrução. A OUTPUT cláusula retorna colunas da tabela que está sendo excluída (DELETED.ProductID, DELETED.ProductPhotoID) e colunas da Product tabela. Esta tabela é usada na FROM cláusula para especificar as linhas a serem excluídas.

USE AdventureWorks2022;
GO

DECLARE @MyTableVar TABLE (
    ProductID INT NOT NULL,
    ProductName NVARCHAR(50)NOT NULL,
    ProductModelID INT NOT NULL,
    PhotoID INT NOT NULL);

DELETE Production.ProductProductPhoto
OUTPUT DELETED.ProductID,
       p.Name,
       p.ProductModelID,
       DELETED.ProductPhotoID
    INTO @MyTableVar
FROM Production.ProductProductPhoto AS ph
JOIN Production.Product as p
    ON ph.ProductID = p.ProductID
    WHERE p.ProductModelID BETWEEN 120 and 130;

--Display the results of the table variable.
SELECT ProductID, ProductName, ProductModelID, PhotoID
FROM @MyTableVar
ORDER BY ProductModelID;
GO

G. Use OUTPUT INTO com um tipo de dados de objeto grande

O exemplo a seguir atualiza um valor parcial em DocumentSummary, uma coluna nvarchar(max) na tabela, usando a Production.Document.WRITE cláusula . A palavra components é substituída pela palavra features especificando a palavra de substituição, a localização inicial (deslocamento) da palavra a substituir nos dados existentes e o número de caracteres a substituir (comprimento). O exemplo usa a OUTPUT cláusula para retornar as imagens de antes e depois da DocumentSummary coluna para a @MyTableVar variável de tabela. As imagens completas de antes e depois da DocumentSummary coluna são retornadas.

USE AdventureWorks2022;
GO

DECLARE @MyTableVar TABLE (
    SummaryBefore NVARCHAR(MAX),
    SummaryAfter NVARCHAR(MAX)
);

UPDATE Production.Document
SET DocumentSummary.WRITE(N'features', 28, 10)
OUTPUT DELETED.DocumentSummary,
       INSERTED.DocumentSummary
    INTO @MyTableVar
WHERE Title = N'Front Reflector Bracket Installation';

SELECT SummaryBefore, SummaryAfter
FROM @MyTableVar;
GO

H. Use OUTPUT em um gatilho EM vez DE

O exemplo a seguir usa a cláusula em um gatilho OUTPUT para retornar os resultados da operação de gatilho. Primeiro, um modo de exibição é criado na tabela e, em ScrapReason seguida, um INSTEAD OF INSERT gatilho é definido no modo de exibição que permite que apenas a Name coluna da tabela base seja modificada pelo usuário. Como a coluna ScrapReasonID é uma IDENTITY coluna na tabela base, o gatilho ignora o valor fornecido pelo usuário. Isso permite que o Mecanismo de Banco de Dados gere automaticamente o valor correto. Além disso, o valor fornecido pelo usuário para ModifiedDate é ignorado e é definido para a data atual. A OUTPUT cláusula retorna os valores realmente inseridos ScrapReason na tabela.

USE AdventureWorks2022;
GO

IF OBJECT_ID('dbo.vw_ScrapReason', 'V') IS NOT NULL
    DROP VIEW dbo.vw_ScrapReason;
GO

CREATE VIEW dbo.vw_ScrapReason
AS
SELECT ScrapReasonID,
    Name,
    ModifiedDate
FROM Production.ScrapReason;
GO

CREATE TRIGGER dbo.io_ScrapReason ON dbo.vw_ScrapReason
INSTEAD OF INSERT
AS
BEGIN
    --ScrapReasonID is not specified in the list of columns to be inserted
    --because it is an IDENTITY column.
    INSERT INTO Production.ScrapReason (
        Name,
        ModifiedDate
    )
    OUTPUT INSERTED.ScrapReasonID,
        INSERTED.Name,
        INSERTED.ModifiedDate
    SELECT Name, GETDATE()
    FROM INSERTED;
END
GO

INSERT vw_ScrapReason (
    ScrapReasonID,
    Name,
    ModifiedDate
)
VALUES (
    99,
    N'My scrap reason',
    '20030404'
);
GO

Aqui está o conjunto de resultados gerado em 12 de abril de 2004 ('2004-04-12'). As ScrapReasonIDActual colunas e ModifiedDate refletem os valores gerados pela operação trigger em vez dos valores fornecidos na INSERT instrução.

ScrapReasonID  Name             ModifiedDate
-------------  ---------------- -----------------------
17             My scrap reason  2004-04-12 16:23:33.050

I. Use OUTPUT INTO com identidade e colunas computadas

O exemplo a seguir cria a EmployeeSales tabela e, em seguida, insere várias linhas nela usando uma INSERT instrução com uma SELECT instrução para recuperar dados de tabelas de origem. A EmployeeSales tabela contém uma coluna de identidade (EmployeeID) e uma coluna computada (ProjectedSales).

USE AdventureWorks2022;
GO

IF OBJECT_ID('dbo.EmployeeSales', 'U') IS NOT NULL
    DROP TABLE dbo.EmployeeSales;
GO

CREATE TABLE dbo.EmployeeSales (
    EmployeeID INT IDENTITY(1, 5) NOT NULL,
    LastName NVARCHAR(20) NOT NULL,
    FirstName NVARCHAR(20) NOT NULL,
    CurrentSales MONEY NOT NULL,
    ProjectedSales AS CurrentSales * 1.10
);
GO

DECLARE @MyTableVar TABLE (
    EmployeeID INT NOT NULL,
    LastName NVARCHAR(20) NOT NULL,
    FirstName NVARCHAR(20) NOT NULL,
    CurrentSales MONEY NOT NULL,
    ProjectedSales MONEY NOT NULL
);

INSERT INTO dbo.EmployeeSales (
    LastName,
    FirstName,
    CurrentSales
)
OUTPUT INSERTED.EmployeeID,
    INSERTED.LastName,
    INSERTED.FirstName,
    INSERTED.CurrentSales,
    INSERTED.ProjectedSales
INTO @MyTableVar
SELECT c.LastName,
    c.FirstName,
    sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c
    ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.BusinessEntityID LIKE '2%'
ORDER BY c.LastName,
    c.FirstName;

SELECT EmployeeID,
    LastName,
    FirstName,
    CurrentSales,
    ProjectedSales
FROM @MyTableVar;
GO

SELECT EmployeeID,
    LastName,
    FirstName,
    CurrentSales,
    ProjectedSales
FROM dbo.EmployeeSales;
GO

J. Use OUTPUT e OUTPUT INTO em uma única instrução

O exemplo a seguir exclui linhas na ProductProductPhoto tabela com base nos critérios de pesquisa definidos na FROM cláusula da DELETE instrução. A OUTPUT INTO cláusula retorna colunas da tabela que está sendo excluída (DELETED.ProductID, DELETED.ProductPhotoID) e colunas da Product tabela para a @MyTableVar variável de tabela. A Product tabela é usada na FROM cláusula para especificar as linhas a serem excluídas. A OUTPUT cláusula retorna as DELETED.ProductIDcolunas , DELETED.ProductPhotoID e a data e hora em que a linha foi excluída da tabela para o ProductProductPhoto aplicativo de chamada.

USE AdventureWorks2022;
GO

DECLARE @MyTableVar TABLE (
    ProductID INT NOT NULL,
    ProductName NVARCHAR(50) NOT NULL,
    ProductModelID INT NOT NULL,
    PhotoID INT NOT NULL
);

DELETE Production.ProductProductPhoto
OUTPUT DELETED.ProductID,
    p.Name,
    p.ProductModelID,
    DELETED.ProductPhotoID
INTO @MyTableVar
OUTPUT DELETED.ProductID,
    DELETED.ProductPhotoID,
    GETDATE() AS DeletedDate
FROM Production.ProductProductPhoto AS ph
INNER JOIN Production.Product AS p
    ON ph.ProductID = p.ProductID
WHERE p.ProductID BETWEEN 800
        AND 810;

--Display the results of the table variable.
SELECT ProductID,
    ProductName,
    PhotoID,
    ProductModelID
FROM @MyTableVar;
GO

K. Inserir dados retornados de uma cláusula OUTPUT

O exemplo a seguir captura dados retornados da OUTPUT cláusula de uma MERGE instrução e insere esses dados em outra tabela. A MERGE instrução atualiza a QuantityProductInventory coluna da tabela diariamente, com base nas ordens que são processadas na SalesOrderDetail tabela. Ele também exclui linhas para produtos cujos estoques caem para 0 ou menos. O exemplo captura as linhas que são excluídas e as insere em outra tabela, ZeroInventoryque rastreia produtos sem inventário.

USE AdventureWorks2022;
GO

IF OBJECT_ID(N'Production.ZeroInventory', N'U') IS NOT NULL
    DROP TABLE Production.ZeroInventory;
GO

--Create ZeroInventory table.
CREATE TABLE Production.ZeroInventory (
    DeletedProductID INT,
    RemovedOnDate DATETIME
    );
GO

INSERT INTO Production.ZeroInventory (
    DeletedProductID,
    RemovedOnDate
)
SELECT ProductID,
    GETDATE()
FROM (
    MERGE Production.ProductInventory AS pi
    USING (
        SELECT ProductID,
            SUM(OrderQty)
        FROM Sales.SalesOrderDetail AS sod
        INNER JOIN Sales.SalesOrderHeader AS soh
            ON sod.SalesOrderID = soh.SalesOrderID
                AND soh.OrderDate = '20070401'
        GROUP BY ProductID
        ) AS src(ProductID, OrderQty)
        ON (pi.ProductID = src.ProductID)
    WHEN MATCHED
        AND pi.Quantity - src.OrderQty <= 0
        THEN
            DELETE
    WHEN MATCHED
        THEN
            UPDATE
            SET pi.Quantity = pi.Quantity - src.OrderQty
    OUTPUT $ACTION,
        DELETED.ProductID
    ) AS Changes(Action, ProductID)
WHERE Action = 'DELETE';

IF @@ROWCOUNT = 0
    PRINT 'Warning: No rows were inserted';
GO

SELECT DeletedProductID,
    RemovedOnDate
FROM Production.ZeroInventory;
GO