實戰篇
A. 將 OUTPUT INTO 用於簡單 INSERT 語句
以下示例將行插入 ScrapReason
表,並使用 OUTPUT
子句將語句的結果返回到 @MyTableVar
table 變量。由於 ScrapReasonID
列使用 IDENTITY 屬性定義,因此未在 INSERT
語句中爲該列指定一個值。但請注意,將在列 INSERTED.ScrapReasonID
內的 OUTPUT
子句中返回由數據庫引擎 爲該列生成的值。
複製代碼 | |
---|---|
USE AdventureWorks; GO DECLARE @MyTableVar table( ScrapReasonID 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 ScrapReasonID, Name, ModifiedDate FROM @MyTableVar; --Display the result set of the table. SELECT ScrapReasonID, Name, ModifiedDate FROM Production.ScrapReason; GO |
B. 將 OUTPUT 用於 INSERT…SELECT 語句
以下示例創建 EmployeeSales
表,然後通過使用 SELECT
語句檢索源表中的數據將幾行插入該表。同時,也計算了列 ProjectedSales
的值並將其插入該表中。OUTPUT
子句將 INSERT
語句的結果返回到執行調用的應用程序。最後的 SELECT
語句驗證新 EmployeeSales
表的內容是否與 OUTPUT
子句的結果匹配。
複製代碼 | |
---|---|
USE AdventureWorks ; GO IF OBJECT_ID ('dbo.EmployeeSales', 'U') IS NOT NULL DROP TABLE dbo.EmployeeSales; GO CREATE TABLE dbo.EmployeeSales ( EmployeeID nvarchar(11) NOT NULL, LastName nvarchar(20) NOT NULL, FirstName nvarchar(20) NOT NULL, CurrentSales money NOT NULL, ProjectedSales money NOT NULL ); GO INSERT INTO dbo.EmployeeSales OUTPUT INSERTED.EmployeeID, INSERTED.LastName, INSERTED.FirstName, INSERTED.CurrentSales, INSERTED.ProjectedSales SELECT e.EmployeeID, c.LastName, c.FirstName, sp.SalesYTD, sp.SalesYTD * 1.10 FROM HumanResources.Employee AS e INNER JOIN Sales.SalesPerson AS sp ON e.EmployeeID = sp.SalesPersonID INNER JOIN Person.Contact AS c ON e.ContactID = c.ContactID WHERE e.EmployeeID LIKE '2%' ORDER BY c.LastName, c.FirstName; GO SELECT EmployeeID, LastName, FirstName, CurrentSales, ProjectedSales FROM dbo.EmployeeSales; GO |
C. 將 OUTPUT 用於 DELETE 語句
以下示例將刪除 ShoppingCartItem
表中的所有行。子句 OUTPUT DELETED.*
指定 DELETE
語句的結果(即已刪除的行中的所有列)返回到執行調用的應用程序。後面的 SELECT
語句驗證對 ShoppingCartItem
表所執行的刪除操作的結果。
複製代碼 | |
---|---|
USE AdventureWorks; GO DELETE Sales.ShoppingCartItem OUTPUT DELETED.* ; --Verify all rows in the table have been deleted. SELECT COUNT(*) AS [Rows in Table] FROM Sales.ShoppingCartItem; GO |
D. 將 OUTPUT INTO 用於 UPDATE
下面的示例將 Employee
表中 VacationHours
列的前 10 行更新 25%。OUTPUT
子句將返回 VacationHours
值,該值在將列 DELETED.VacationHours
中的 UPDATE
語句和列 INSERTED.VacationHours
中的已更新值應用於 @MyTableVar
table 變量之前存在。
在它後面的兩個 SELECT
語句返回 @MyTableVar
中的值以及 Employee
表中更新操作的結果。請注意,INSERTED.ModifiedDate
列中的結果與 Employee
表中的 ModifiedDate
列不具有相同的值。這是因爲對 Employee
表定義了將 ModifiedDate
的值更新爲當前日期的 AFTER UPDATE 觸發器。但是,從 OUTPUT 中返回的列反映觸發器激發之前的數據。
複製代碼 | |
---|---|
USE AdventureWorks; GO DECLARE @MyTableVar table( EmpID int NOT NULL, OldVacationHours int, NewVacationHours int, ModifiedDate datetime); UPDATE TOP (10) HumanResources.Employee SET VacationHours = VacationHours * 1.25 OUTPUT INSERTED.EmployeeID, 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. --Note that ModifiedDate reflects the value generated by an --AFTER UPDATE trigger. SELECT TOP (10) EmployeeID, VacationHours, ModifiedDate FROM HumanResources.Employee; GO |
E. 使用 OUTPUT INTO 返回表達式
以下示例在示例 D 的基礎上生成,方法是通過將 OUTPUT 子句中的表達式定義爲已更新的 VacationHours
值與應用更新之前的 VacationHours
值之間的差異。該表達式的值返回到列 VacationHoursDifference
中的 @MyTableVar
table 變量。
複製代碼 | |
---|---|
USE AdventureWorks; 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 OUTPUT INSERTED.EmployeeID, 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) EmployeeID, VacationHours, ModifiedDate FROM HumanResources.Employee; GO |
F. 在 UPDATE 語句中使用包含 from_table_name 的 OUTPUT INTO
以下示例使用指定的 ProductID
和 ScrapReasonID
,針對 WorkOrder
表中的所有工作順序更新 ScrapReasonID
列。OUTPUT INTO
子句返回所更新表 (WorkOrder
) 中的值以及 Product
表中的值。在 FROM 子句中使用 Product
表來指定要更新的行。由於 WorkOrder
表具有對其定義的 AFTER UPDATE 觸發器,因此需要 INTO 關鍵字。
複製代碼 | |
---|---|
USE AdventureWorks; 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 |
G. 在 DELETE 語句中使用包含 from_table_name 的 OUTPUT INTO
以下示例將按照在 DELETE
語句的 FROM
子句中所定義的搜索條件刪除 ProductProductPhoto
表中的行。OUTPUT
子句返回所刪除表(DELETED.ProductID
、DELETED.ProductPhotoID
)中的列以及 Product
表中的列。在 FROM
子句中使用該表來指定要刪除的行。
複製代碼 | |
---|---|
USE AdventureWorks 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 |
H. 將 OUTPUT INTO 用於大型對象數據類型
以下示例使用 .WRITE
子句更新 Production.Document
表內 DocumentSummary
這一 nvarchar(max) 列中的部分值。通過指定替換單詞、現有數據中要替換的單詞的開始位置(偏移量)以及要替換的字符數(長度),將單詞 components
替換爲單詞 features
。此示例使用 OUTPUT
子句將 DocumentSummary
列的前像和後像返回到 @MyTableVar
table 變量。請注意,將返回 DocumentSummary
列的全部前像和後像。
複製代碼 | |
---|---|
USE AdventureWorks; GO DECLARE @MyTableVar table ( DocumentID int NOT NULL, SummaryBefore nvarchar(max), SummaryAfter nvarchar(max)); UPDATE Production.Document SET DocumentSummary .WRITE (N'features',28,10) OUTPUT INSERTED.DocumentID, DELETED.DocumentSummary, INSERTED.DocumentSummary INTO @MyTableVar WHERE DocumentID = 3 ; SELECT DocumentID, SummaryBefore, SummaryAfter FROM @MyTableVar; GO |
I. 在 INSTEAD OF 觸發器中使用 OUTPUT
以下示例在觸發器中使用 OUTPUT 子句返回觸發器操作的結果。首先,創建一個 ScrapReason
表的視圖,然後對該視圖定義 INSTEAD OF INSERT
觸發器,從而使用戶只修改基表的 Name
列。由於列 ScrapReasonID
是基表中的 IDENTITY 列,因此觸發器將忽略用戶提供的值。這允許數據庫引擎 自動生成正確的值。同樣,用戶爲 ModifiedDate
提供的值也被忽略並設置爲正確的日期。OUTPUT
子句返回實際插入 ScrapReason
表中的值。
複製代碼 | |
---|---|
UUSE AdventureWorks; 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 |
這是在 2004 年 4 月 12 日 ('2004-04-12'
) 生成的結果集。請注意,ScrapReasonIDActual
和 ModifiedDate
列反映由觸發器操作生成的值而不是 INSERT
語句中提供的值。
複製代碼 | |
---|---|
ScrapReasonID Name ModifiedDate ------------- ---------------- ----------------------- 17 My scrap reason 2004-04-12 16:23:33.050 |
J. 將 OUTPUT INTO 用於標識列和計算列
下面的示例創建 EmployeeSales
表,然後使用 INSERT 語句向其中插入若干行,並使用 SELECT 語句從源表中檢索數據。EmployeeSales
表包含標識列 (EmployeeID
) 和計算列 (ProjectedSales
)。由於這些值是在插入操作期間由數據庫引擎生成的,因此,不能在 @MyTableVar
中定義上述兩列。
複製代碼 | |
---|---|
USE AdventureWorks ; 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( LastName nvarchar(20) NOT NULL, FirstName nvarchar(20) NOT NULL, CurrentSales money NOT NULL ); INSERT INTO dbo.EmployeeSales (LastName, FirstName, CurrentSales) OUTPUT INSERTED.LastName, INSERTED.FirstName, INSERTED.CurrentSales INTO @MyTableVar SELECT c.LastName, c.FirstName, sp.SalesYTD FROM HumanResources.Employee AS e INNER JOIN Sales.SalesPerson AS sp ON e.EmployeeID = sp.SalesPersonID INNER JOIN Person.Contact AS c ON e.ContactID = c.ContactID WHERE e.EmployeeID LIKE '2%' ORDER BY c.LastName, c.FirstName; SELECT LastName, FirstName, CurrentSales FROM @MyTableVar; GO SELECT EmployeeID, LastName, FirstName, CurrentSales, ProjectedSales FROM dbo.EmployeeSales; GO |
在單個語句中使用 OUTPUT 與 OUTPUT INTO
以下示例將按照在 DELETE
語句的 FROM
子句中所定義的搜索條件刪除 ProductProductPhoto
表中的行。OUTPUT INTO
子句將所刪除表(DELETED.ProductID
、DELETED.ProductPhotoID
)中的列以及 Product
表中的列返回到 @MyTableVar
table 變量。在 FROM
子句中使用 Product
表來指定要刪除的行。OUTPUT
子句將 ProductProductPhoto
表中的 DELETED.ProductID
、DELETED.ProductPhotoID
列以及行的刪除日期和時間返回到執行調用的應用程序。
複製代碼 | |
---|---|
USE AdventureWorks 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 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 |