簡體   English   中英

在sql server中使用OUTPUT子句有什么用

[英]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語句,它將具有DELETEDINSERTED表。 在執行更新操作之前, 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM