[英]What is the use of OUTPUT clause in sql server
OUTPUT
子句的目的是什么? 我已經閱讀了OUTPUT
子句的MSDN文檔 ,其中包括以下示例:
DELETE FROM dbo.table1
OUTPUT DELETED.* INTO @MyTableVar
WHERE id = 4 OR id = 2;
從上面的查詢中,似乎已刪除的記錄保存在一些名為deleted
魔術表中,並且查詢會將這些記錄從魔術deleted
表中加載到名為MyTableVar的表中。 。
我仍然不明白OUTPUT
子句用法的目的。
作為另一個SQL示例:
USE AdventureWorks2012;
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
這到底是做什么的? 有人能用一個簡單的例子來解釋這個子句的用處嗎?
create proc test
as
CREATE TABLE dbo.table1
(
id INT,
employee VARCHAR(32)
)
go
INSERT INTO dbo.table1 VALUES
(1, 'Fred')
,(2, 'Tom')
,(3, 'Sally')
,(4, 'Alice')
delete from table1
select * from deleted
當我運行它時,這會給我一個錯誤,因為它無法看到deleted
表。
此子句的一般目的是捕獲對數據所做的更改,而無需額外的查詢,這會引入鎖定和阻塞問題。 例:
DELETE FROM X WHERE Name = 'Foo'
您想知道哪些ID已被刪除。 你可以像這樣天真地做到這一點:
SELECT ID FROM X WHERE Name = 'Foo'
DELETE FROM X WHERE Name = 'Foo'
但是這些選定的ID是不可靠的,除非您在具有隔離級別SERIALIZABLE
的事務中運行,這通常不是這種情況。 其他人可以添加,刪除或更改兩個語句之間的“Foo” - 記錄。 因此,您可以使用OUTPUT子句並准確可靠地獲取已刪除的ID,而不會出現任何性能或可靠性問題。
另一種常用方法是獲取插入的默認值的值,尤其是在使用標識列時。 對於單個插入,您可以這樣做:
CREATE TABLE X
(
ID INT IDENTITY,
Name VARCHAR(10)
);
INSERT X (Name) VALUES ('Foo')
SELECT SCOPE_IDENTITY()
但是SCOPE_IDENTITY()
只能為您提供最后插入的ID。 如果你做多個插入,比如
INSERT X (Name) VALUES ('Foo'), ('Bar')
要么
INSERT X (Name) SELECT OtherName FROM Y
而你想知道插入的ID,你運氣不好。 您可以嘗試使用另一個SELECT找到它們,但是您需要另一個唯一列來構建查詢,然后遇到與上面的DELETE
示例相同的問題。 因此, OUTPUT
子句允許您整齊地識別哪些名稱獲得了哪些ID。
例如,在使用外鍵創建相關記錄時,您將需要這些ID。 認為“Order”和“OrderDetails”由OrderID列與IDENTITY
子句鏈接。 同樣,使用單個INSERT,您可以使用SCOPE_IDENTITY()
或@@IDENTITY
,但是當一次插入多個訂單時,您將需要OUTPUT
。
在特定表上執行插入/更新/刪除操作並想知道哪些行受影響或想要將它們記錄為審計跟蹤時,或者您希望在后續sql語句中使用受影響行的多個值時,可以使用OUTPUT
子句。
對於Insert語句,它將具有INSERTED
表。
對於Delete語句,它將具有DELETED
表。 在更新的情況下, DELETED
表將在執行更新操作之前包含行(具有舊值)。
對於Update語句,它將具有DELETED
和INSERTED
表。 在執行更新操作之前, DELETED
表將包含行(具有舊值)。 執行更新操作后, INSERTED
表將包含行(具有新值)。
USE AdventureWorks2012;
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;
現在,您的查詢在Production.ScrapReason
插入行以及表變量@MyTableVar
。 稍后它從Production.ScrapReason
和@MyTableVar
選擇插入的行。 因此,您可以比較結果集,並且它必須具有相同的行(考慮到Production.ScrapReason
是空表。)
我希望它有意義!
編輯:
插入/刪除表格將在插入/更新/刪除語句中提供,之后不會。 您可能希望將這些魔術表值存儲在db table或temp table中。
沒有OUTPUT
子句,您如何知道刪除了哪些行? 您的示例看起來很簡單,因為您已經知道了Id
值,但是如果您這樣做會怎樣:
DELETE FROM T WHERE SomeColumn LIKE 'SomePattern%'
你想知道刪除了什么。 這就是OUTPUT
子句的目的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.