Udostępnij za pomocą


KLAUZULA OUTPUT (Transact-SQL)

Dotyczy:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceBaza danych SQL w usłudze Microsoft Fabric

Zwraca informacje z wyrażenia lub na podstawie każdego wiersza, którego dotyczy INSERTinstrukcja , UPDATE, lub DELETEMERGE . Te wyniki można zwrócić do aplikacji przetwarzania do użycia w takich sytuacjach, jak komunikaty potwierdzające, archiwizacja i inne wymagania aplikacji. Wyniki można również wstawić do tabeli lub zmiennej tabeli. Ponadto można przechwycić wyniki klauzuli OUTPUT w zagnieżdżonej INSERTinstrukcji , UPDATE, DELETElub MERGE i wstawić te wyniki do tabeli docelowej lub widoku.

Note

Instrukcja UPDATE, INSERTlub DELETE zawierająca klauzulę OUTPUT zwraca wiersze do klienta, nawet jeśli instrukcja napotka błędy i zostanie wycofana. Wynik nie powinien być używany, jeśli wystąpi jakikolwiek błąd podczas uruchamiania instrukcji .

Wykorzystywane w:

Transact-SQL konwencje składni

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

Określa zmienną tabeli , w którą zwracane wiersze są wstawiane zamiast zwracać do obiektu wywołującego. @table_variable należy zadeklarować przed instrukcją INSERT, UPDATE, DELETElub MERGE .

Jeśli nie określono column_list , zmienna tabeli musi mieć taką samą liczbę kolumn jak OUTPUT zestaw wyników. Wyjątki to kolumny tożsamości i obliczone, które muszą zostać pominięte. Jeśli określono column_list , wszystkie pominięte kolumny muszą zezwalać na wartości null lub mieć przypisane wartości domyślne.

Aby uzyskać więcej informacji na temat zmiennych tabeli , zobacz tabelę.

output_table

Określa tabelę, w którą zwracane wiersze są wstawiane zamiast zwracane do obiektu wywołującego. output_table może być tabelą tymczasową.

Jeśli nie określono column_list , tabela musi mieć taką samą liczbę kolumn jak OUTPUT zestaw wyników. Wyjątki to kolumny tożsamości i obliczone, które muszą zostać pominięte. Jeśli określono column_list , wszystkie pominięte kolumny muszą zezwalać na wartości null lub mieć przypisane wartości domyślne.

output_table nie może:

  • Włączone wyzwalacze zostały zdefiniowane na nim.
  • Weź udział po obu stronach FOREIGN KEY ograniczenia.
  • Mają CHECK ograniczenia lub włączone reguły.

column_list

Opcjonalna lista nazw kolumn w tabeli docelowej klauzuli INTO . Jest ona analogiczna do listy kolumn dozwolonych w instrukcji INSERT .

scalar_expression

Dowolna kombinacja symboli i operatorów, które oblicza pojedynczą wartość. Funkcje agregujące nie są dozwolone w scalar_expression.

Każde odwołanie do kolumn w modyfikowanej tabeli musi być kwalifikowane za pomocą prefiksu INSERTED lub DELETED .

column_alias_identifier

Alternatywna nazwa używana do odwołowania się do nazwy kolumny.

DELETED

Prefiks kolumny określający wartość usuniętą przez operację aktualizacji lub usuwania oraz wszelkie istniejące wartości, które nie zmieniają się przy użyciu bieżącej operacji. Kolumny poprzedzone prefiksem DELETED odzwierciedlają wartość przed ukończeniem instrukcji UPDATE, DELETElub MERGE .

DELETED Nie można użyć klauzuli OUTPUT w instrukcji INSERT .

WSTAWIONY

Prefiks kolumny określający wartość dodaną przez operację wstawiania lub aktualizacji oraz wszelkie istniejące wartości, które nie zmieniają się przy użyciu bieżącej operacji. Kolumny poprzedzone prefiksem INSERTED odzwierciedlają wartość po zakończeniu UPDATEinstrukcji , INSERTlub MERGE , ale przed wykonaniem wyzwalaczy.

INSERTED Nie można użyć klauzuli OUTPUT w instrukcji DELETE .

from_table_name

Prefiks kolumny określający tabelę zawartą w FROM klauzuli DELETE, UPDATElub MERGE instrukcji używanej do określania wierszy do aktualizowania lub usuwania.

Jeśli modyfikowana tabela jest również określona w klauzuli FROM , wszelkie odwołania do kolumn w tej tabeli muszą być kwalifikowane z prefiksem INSERTED lub DELETED .

*

Gwiazdka (*) określa, że wszystkie kolumny, na które ma wpływ akcja usuwania, wstawiania lub aktualizacji, są zwracane w kolejności, w jakiej istnieją w tabeli.

Na przykład OUTPUT DELETED.* w poniższej DELETE instrukcji zwraca wszystkie kolumny usunięte z ShoppingCartItem tabeli:

DELETE Sales.ShoppingCartItem
    OUTPUT DELETED.*;

column_name

Jawne odwołanie do kolumny. Wszelkie odwołania do modyfikowanej tabeli muszą być poprawnie kwalifikowane przez INSERTED prefiks lub DELETED odpowiednio, na przykład: INSERTED.<column_name>.

$action

Dostępne tylko dla instrukcji MERGE . Określa kolumnę typu nvarchar(10) w klauzuli w OUTPUTMERGE instrukcji zwracającej jedną z trzech wartości dla każdego wiersza: INSERT, UPDATElub DELETE, zgodnie z akcją wykonywaną w tym wierszu.

Remarks

Klauzulę OUTPUT <dml_select_list> i klauzulę OUTPUT <dml_select_list> INTO { @table_variable | output_table } można zdefiniować w jednej INSERTinstrukcji , UPDATE, lub .DELETEMERGE

Note

O ile nie określono inaczej, odwołania do klauzuli odnoszą się zarówno do OUTPUT klauzuli, jak OUTPUT i klauzuli OUTPUT INTO .

Klauzula OUTPUT może być przydatna do pobierania wartości tożsamości lub obliczonych kolumn po INSERT operacji lub UPDATE .

Gdy kolumna obliczeniowa jest uwzględniona w kolumnie <dml_select_list>, odpowiadająca jej kolumna w tabeli wyjściowej lub zmiennej tabeli nie jest kolumną obliczeniową. Wartości w nowej kolumnie to wartości, które zostały obliczone podczas wykonywania instrukcji.

Kolejność stosowania zmian do tabeli oraz kolejność wstawiania wierszy do tabeli wyjściowej lub zmiennej tabeli nie jest gwarantowana.

Jeśli parametry lub zmienne są modyfikowane w ramach UPDATE instrukcji, OUTPUT klauzula zawsze zwraca wartość parametru lub zmiennej, jak to było przed wykonaniem instrukcji zamiast zmodyfikowanej wartości.

Można użyć OUTPUT z instrukcją UPDATE lub DELETE umieszczoną na kursorze, który używa WHERE CURRENT OF składni.

Klauzula nie jest obsługiwana OUTPUT w następujących instrukcjach:

  • Instrukcje DML odwołujące się do lokalnych widoków partycjonowanych, rozproszonych widoków partycjonowanych lub tabel zdalnych.

  • INSERT instrukcje zawierające instrukcję EXECUTE .

  • Predykaty pełnotekstowe nie są dozwolone w OUTPUT klauzuli , gdy poziom zgodności bazy danych jest ustawiony na 100.

  • Klauzula OUTPUT INTO nie może służyć do wstawiania do widoku ani funkcji zestawu wierszy.

  • Nie można utworzyć funkcji zdefiniowanej przez użytkownika, jeśli zawiera ona klauzulę zawierającą OUTPUT INTO tabelę jako element docelowy.

Aby zapobiec nieokreślonemu zachowaniu, klauzula OUTPUT nie może zawierać następujących odwołań:

  • Podzapytania lub funkcje zdefiniowane przez użytkownika, które wykonują dostęp do danych użytkownika lub systemu, lub zakłada się, że mają taki dostęp. Zakłada się, że funkcje zdefiniowane przez użytkownika wykonują dostęp do danych, jeśli nie są powiązane ze schematem.

  • Kolumna z widoku lub wbudowanej funkcji wartości tabeli, gdy ta kolumna jest definiowana przez jedną z następujących metod:

    • Subquery.

    • Zdefiniowana przez użytkownika funkcja, która wykonuje dostęp do danych użytkownika lub systemu, lub przyjmuje się, że wykonuje taki dostęp.

    • Obliczona kolumna zawierająca funkcję zdefiniowaną przez użytkownika, która wykonuje dostęp do danych użytkownika lub systemu w definicji.

    Gdy program SQL Server wykryje taką kolumnę w klauzuli OUTPUT , zostanie zgłoszony błąd 4186.

Wstawianie danych zwracanych z klauzuli OUTPUT do tabeli

Podczas przechwytywania wyników klauzuli OUTPUT w zagnieżdżonej INSERTinstrukcji , UPDATE, DELETElub MERGE i wstawiania tych wyników do tabeli docelowej należy pamiętać o następujących informacjach:

  • Cała operacja jest niepodzielna. Zarówno INSERT instrukcja, jak i zagnieżdżona instrukcja DML zawierająca klauzulę OUTPUT execute, lub cała instrukcja kończy się niepowodzeniem.

  • Następujące ograniczenia dotyczą obiektu docelowego instrukcji zewnętrznej INSERT :

    • Obiekt docelowy nie może być tabelą zdalną, widokiem ani typowym wyrażeniem tabeli.

    • Obiekt docelowy nie może mieć FOREIGN KEY ograniczenia ani nie może być przywoływane przez FOREIGN KEY ograniczenie.

    • Wyzwalacze nie mogą być zdefiniowane w obiekcie docelowym.

    • Obiekt docelowy nie może uczestniczyć w replikacji scalania ani aktualizowalnych subskrypcji na potrzeby replikacji transakcyjnej.

  • Następujące ograniczenia dotyczą zagnieżdżonej instrukcji DML:

    • Obiekt docelowy nie może być tabelą zdalną ani widokiem podzielonym na partycje.

    • Samo źródło nie może zawierać klauzuli <dml_table_source> .

  • Klauzula nie jest obsługiwana OUTPUT INTO w INSERT instrukcjach zawierających klauzulę <dml_table_source> .

  • @@ROWCOUNT Zwraca wiersze wstawione tylko przez instrukcję zewnętrzną INSERT .

  • @@IDENTITY, SCOPE_IDENTITYi IDENT_CURRENT zwracane wartości tożsamości generowane tylko przez zagnieżdżonych instrukcji DML, a nie wartości generowane przez instrukcję zewnętrzną INSERT .

  • Powiadomienia zapytań traktują instrukcję jako pojedynczą jednostkę, a typ tworzonego komunikatu jest typem zagnieżdżonego kodu DML, nawet jeśli znacząca zmiana pochodzi z samej instrukcji zewnętrznej INSERT .

  • W klauzuli <dml_table_source>SELECT i WHERE klauzule nie mogą zawierać podzapytania, funkcji agregujących, funkcji klasyfikacji, predykatów pełnotekstowych, funkcji zdefiniowanych przez użytkownika, które wykonują dostęp do danych lub TEXTPTR() funkcji.

Parallelism

Klauzula zwracająca OUTPUT wyniki do klienta lub zmiennej tabeli, zawsze używa planu szeregowego.

W kontekście bazy danych ustawionej na poziom zgodności 130 lub wyższy, jeśli INSERT...SELECT operacja używa WITH (TABLOCK) wskazówki dla SELECT instrukcji, a także używa OUTPUT...INTO metody wstawiania do tabeli tymczasowej lub użytkownika, tabela docelowa obiektu INSERT...SELECT kwalifikuje się do równoległości w zależności od kosztu poddrzewa. Tabela docelowa, do których odwołuje się klauzula OUTPUT INTO , nie kwalifikuje się do równoległości.

Triggers

Kolumny zwracane z OUTPUT danych są widoczne po zakończeniu INSERTinstrukcji , UPDATElub DELETE , ale przed wykonaniem wyzwalaczy.

W przypadku INSTEAD OF wyzwalaczy zwrócone wyniki są generowane tak, jakby INSERTelement , UPDATElub DELETE rzeczywiście wystąpił, nawet jeśli żadne modyfikacje nie zostaną wprowadzone w wyniku operacji wyzwalacza. Jeśli instrukcja zawierająca klauzulę zawiera klauzulę OUTPUT wewnątrz treści wyzwalacza, aliasy tabeli muszą być używane do odwołowania się do wstawianej i usuniętej tabel wyzwalacza, aby uniknąć duplikowania odwołań do kolumn z tabelami i INSERTED skojarzonymi z DELETEDOUTPUT.

Jeśli klauzula OUTPUT jest określona bez określania również słowa kluczowego INTO , element docelowy operacji DML nie może mieć żadnego włączonego wyzwalacza zdefiniowanego dla danej akcji DML. Jeśli na przykład klauzula OUTPUT jest zdefiniowana w UPDATE instrukcji, tabela docelowa nie może mieć żadnych włączonych UPDATE wyzwalaczy.

sp_configure Jeśli opcja nie zezwala na wyniki z wyzwalaczy jest ustawiona, OUTPUT klauzula bez INTO klauzuli powoduje niepowodzenie instrukcji po wywołaniu z poziomu wyzwalacza.

Typy danych

Klauzula OUTPUT obsługuje duże typy danych obiektów: nvarchar(max), varchar(max), varbinary(max), text, ntext, image i xml. Jeśli używasz .WRITE klauzuli w UPDATE instrukcji , aby zmodyfikować nvarchar(max), varchar(max)lub varbinary(max) kolumny, pełne przed i po obrazach wartości są zwracane, jeśli są przywoływane. Funkcja TEXTPTR() nie może być wyświetlana jako część wyrażenia w kolumnie tekstowej, ntekstowej ani obrazu w klauzuli OUTPUT .

Queues

Można użyć OUTPUT w aplikacjach, które używają tabel jako kolejek lub do przechowywania zestawów wyników pośrednich. Oznacza to, że aplikacja stale dodaje lub usuwa wiersze z tabeli. W poniższym przykładzie użyto klauzuli OUTPUT w instrukcji w DELETE celu zwrócenia usuniętego wiersza do aplikacji wywołującej.

USE AdventureWorks2022;
GO

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

Ten przykład usuwa wiersz z tabeli używanej jako kolejka i zwraca usunięte wartości do aplikacji przetwarzania w jednej akcji. Można również zaimplementować inne semantyki, takie jak użycie tabeli do zaimplementowania stosu. Jednak program SQL Server nie gwarantuje kolejności przetwarzania i zwracania wierszy przy użyciu klauzuli OUTPUT DML. Aplikacja musi zawierać odpowiednią WHERE klauzulę, która może zagwarantować żądaną semantykę lub zrozumieć, że gdy wiele wierszy może kwalifikować się do operacji DML, nie ma gwarantowanej kolejności. W poniższym przykładzie użyto podzapytania i przyjęto założenie, że unikatowość jest cechą DatabaseLogID kolumny w celu zaimplementowania żądanej semantyki porządkowania.

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;

Oto wyniki:

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

READPAST Użyj wskazówek tabeli w instrukcjach UPDATE i DELETE , jeśli scenariusz umożliwia wielu aplikacjom wykonywanie destruktywnego odczytu z jednej tabeli. Zapobiega to problemom z blokowaniem, które mogą wystąpić, jeśli inna aplikacja już odczytuje pierwszy rekord kwalifikujący się w tabeli.

Permissions

SELECT uprawnienia są wymagane dla wszystkich kolumn pobranych za pośrednictwem <dml_select_list> lub używanych w programie <scalar_expression>.

INSERT uprawnienia są wymagane dla wszystkich tabel określonych w pliku <output_table>.

Examples

Przykłady kodu w tym artykule korzystają z przykładowej bazy danych AdventureWorks2025 lub AdventureWorksDW2025, którą można pobrać ze strony głównej Przykładów programu Microsoft SQL Server i projektów społeczności.

A. Używanie funkcji OUTPUT INTO z instrukcją INSERT

Poniższy przykład wstawia wiersz do ScrapReason tabeli i używa OUTPUT klauzuli , aby zwrócić wyniki instrukcji do zmiennej @MyTableVar tabeli. Ponieważ kolumna ScrapReasonID jest zdefiniowana za pomocą właściwości IDENTITY, wartość nie jest określona w instrukcji INSERT dla tej kolumny. Jednak wartość wygenerowana przez aparat bazy danych dla tej kolumny jest zwracana w OUTPUT klauzuli w kolumnie 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. Używanie instrukcji OUTPUT z instrukcją DELETE

Poniższy przykład usuwa wszystkie wiersze w ShoppingCartItem tabeli. Klauzula OUTPUT DELETED.* określa, że wyniki instrukcji DELETE , czyli wszystkie kolumny w usuniętych wierszach, są zwracane do aplikacji wywołującej. Poniższa SELECT instrukcja weryfikuje wyniki operacji usuwania w ShoppingCartItem tabeli.

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. Używanie funkcji OUTPUT INTO z instrukcją UPDATE

Poniższy przykład aktualizuje kolumnę VacationHours w Employee tabeli o 25 procent dla pierwszych 10 wierszy. Klauzula OUTPUT zwraca VacationHours wartość, która istnieje przed zastosowaniem UPDATE instrukcji w kolumnie DELETED.VacationHours, i zaktualizowaną wartość w kolumnie INSERTED.VacationHours do zmiennej @MyTableVar tabeli.

Następuje dwie SELECT instrukcje, które zwracają wartości w @MyTableVar tabeli i wyniki operacji aktualizacji w Employee tabeli.

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. Zwracanie wyrażenia za pomocą funkcji OUTPUT INTO

Poniższy przykład opiera się na przykładzie języka C, definiując wyrażenie w OUTPUT klauzuli jako różnicę między zaktualizowaną VacationHours wartością a VacationHours wartością przed zastosowaniem aktualizacji. Wartość tego wyrażenia jest zwracana do zmiennej @MyTableVar tabeli w kolumnie 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. Używanie funkcji OUTPUT INTO z from_table_name w instrukcji UPDATE

Poniższy przykład aktualizuje kolumnę ScrapReasonID w WorkOrder tabeli dla wszystkich zamówień roboczych z określonymi ProductID wartościami i ScrapReasonID. Klauzula OUTPUT INTO zwraca wartości z tabeli aktualizowanej (WorkOrder), a także z Product tabeli. Tabela Product jest używana w klauzuli FROM , aby określić wiersze do zaktualizowania. Ponieważ tabela WorkOrder ma AFTER UPDATE zdefiniowany wyzwalacz, INTO słowo kluczowe jest wymagane.

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. Używanie funkcji OUTPUT INTO z from_table_name w instrukcji DELETE

Poniższy przykład usuwa wiersze w ProductProductPhoto tabeli na podstawie kryteriów wyszukiwania zdefiniowanych w FROM klauzuli instrukcji DELETE . Klauzula OUTPUT zwraca kolumny z tabeli usuwanej (DELETED.ProductID, DELETED.ProductPhotoID) i kolumn z Product tabeli. Ta tabela jest używana w klauzuli FROM , aby określić wiersze do usunięcia.

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. Używanie funkcji OUTPUT INTO z dużym typem danych obiektu

Poniższy przykład aktualizuje wartość częściową w DocumentSummarykolumnie nvarchar(max) w Production.Document tabeli przy użyciu klauzuli .WRITE . Wyraz components jest zastępowany przez wyraz features , określając wyraz zastępczy, lokalizację początkową (przesunięcie) wyrazu, który ma zostać zastąpiony w istniejących danych, oraz liczbę znaków do zastąpienia (długość). W przykładzie użyto klauzuli OUTPUT , aby zwrócić wartości przed i po obrazach DocumentSummary kolumny do zmiennej @MyTableVar tabeli. Zwracane są pełne obrazy DocumentSummary kolumny i po nim.

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. Używanie danych WYJŚCIOWYch w wyzwalaczu ZAMIAST wyzwalacza

W poniższym przykładzie użyto klauzuli OUTPUT w wyzwalaczu, aby zwrócić wyniki operacji wyzwalacza. Najpierw w tabeli jest tworzony ScrapReason widok, a następnie INSTEAD OF INSERT wyzwalacz jest definiowany w widoku, który umożliwia modyfikowanie tylko Name kolumny tabeli bazowej przez użytkownika. Ponieważ kolumna jest kolumną ScrapReasonIDIDENTITY w tabeli podstawowej, wyzwalacz ignoruje wartość podaną przez użytkownika. Dzięki temu aparat bazy danych może automatycznie wygenerować poprawną wartość. Ponadto wartość podana przez użytkownika ModifiedDate jest ignorowana i jest ustawiona na bieżącą datę. Klauzula OUTPUT zwraca wartości rzeczywiście wstawione do ScrapReason tabeli.

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

Oto zestaw wyników wygenerowany 12 kwietnia 2004 r. ('2004-04-12'). Kolumny ScrapReasonIDActual i ModifiedDate odzwierciedlają wartości wygenerowane przez operację wyzwalacza zamiast wartości podanych w instrukcji INSERT .

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

I. Używanie funkcji OUTPUT INTO z kolumnami tożsamości i obliczonymi

Poniższy przykład tworzy tabelę EmployeeSales , a następnie wstawia do niej kilka wierszy przy użyciu INSERT instrukcji z instrukcją SELECT w celu pobrania danych z tabel źródłowych. Tabela EmployeeSales zawiera kolumnę tożsamości (EmployeeID) i obliczoną kolumnę (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. Używanie funkcji OUTPUT i OUTPUT INTO w jednej instrukcji

Poniższy przykład usuwa wiersze w ProductProductPhoto tabeli na podstawie kryteriów wyszukiwania zdefiniowanych w FROM klauzuli instrukcji DELETE . Klauzula OUTPUT INTO zwraca kolumny z tabeli usuwanej (DELETED.ProductID, DELETED.ProductPhotoID) i kolumn z Product tabeli do zmiennej @MyTableVar tabeli. Tabela Product jest używana w klauzuli FROM , aby określić wiersze do usunięcia. Klauzula OUTPUT zwraca DELETED.ProductIDkolumny , DELETED.ProductPhotoID oraz datę i godzinę usunięcia wiersza z ProductProductPhoto tabeli do aplikacji wywołującej.

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. Wstawianie danych zwracanych z klauzuli OUTPUT

Poniższy przykład przechwytuje dane zwrócone z OUTPUT klauzuli instrukcji MERGE i wstawia te dane do innej tabeli. Instrukcja MERGE aktualizuje kolumnę QuantityProductInventory tabeli codziennie na podstawie zamówień przetwarzanych w SalesOrderDetail tabeli. Usuwa również wiersze dla produktów, których zapasy spadają do 0 lub mniej. W przykładzie przechwytuje usunięte wiersze i wstawia je do innej tabeli, ZeroInventoryktóra śledzi produkty bez spisu.

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