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

[英]What is the use of OUTPUT clause in sql server


What is the purpose of the OUTPUT clause? I have gone through the MSDN documentation for the OUTPUT clause, which includes the following example:

OUTPUT子句的目的是什么?我已經閱讀了OUTPUT子句的MSDN文檔,其中包括以下示例:

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

From the above query, it seems that deleted records are saved in some magic table called deleted, and the query will load those records into table called MyTableVar from the magic deleted table. .

從上面的查詢中,似乎已刪除的記錄保存在一些名為deleted的魔術表中,並且查詢將從魔術刪除表中將這些記錄加載到名為MyTableVar的表中。 。

I still do not understand the purpose of the OUTPUT clause usage.

我仍然不明白OUTPUT子句用法的目的。

As another SQL example:

作為另一個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

What is this actually doing? Can anyone explain what this clause is doing with an easy example?

這到底是做什么的?任何人都可以用一個簡單的例子來解釋這個子句的用處嗎?

UPDATE with non-functioning example:

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

This gives me an error when I run it, because it can't see the deleted table.

當我運行它時,這給了我一個錯誤,因為它無法看到已刪除的表。

3 个解决方案

#1


7  

The general purpose of this clause is to capture the changes made to your data without an additional query, which would introduce locking and blocking issues. Example:

此子句的一般目的是捕獲對數據所做的更改,而無需額外的查詢,這會引入鎖定和阻塞問題。例:

DELETE FROM X WHERE Name = 'Foo'

You want to know which IDs were deleted. You can do this naively like this:

您想知道哪些ID已刪除。你可以像這樣天真地做到這一點:

SELECT ID FROM X WHERE Name = 'Foo'
DELETE FROM X WHERE Name = 'Foo'

But these selected IDs are unreliable unless you are running in a transaction with isolation level SERIALIZABLE which is usually not the case. Someone else can add, delete or change "Foo"-Records between your two statements. So instead you can use the OUTPUT clause and get back exactly and reliably the deleted IDs without any performance or reliability issues.

但是這些選定的ID是不可靠的,除非您在具有隔離級別SERIALIZABLE的事務中運行,這通常不是這種情況。其他人可以添加,刪除或更改兩個語句之間的“Foo” - 記錄。因此,您可以使用OUTPUT子句並准確可靠地獲取已刪除的ID,而不會出現任何性能或可靠性問題。

Another frequent use is to get the value of inserted default values, especially when using identity columns. For a single insert you can do this:

另一種常用方法是獲取插入的默認值的值,尤其是在使用標識列時。對於單個插入,您可以執行以下操作:

CREATE TABLE X
 (
 ID INT IDENTITY,
 Name VARCHAR(10)
 );

INSERT X (Name) VALUES ('Foo')

SELECT SCOPE_IDENTITY()

But SCOPE_IDENTITY() can give you only the last inserted ID. If you do multiple inserts, like

但是SCOPE_IDENTITY()只能為您提供最后插入的ID。如果你做多個插入,比如

INSERT X (Name) VALUES ('Foo'), ('Bar')

or

INSERT X (Name) SELECT OtherName FROM Y

and you want to know the inserted IDs, you are out of luck. You can try to find them with another SELECT, but you need another unique column to even formulate the query and then you run into the same issues as with the DELETE sample above. So, the OUTPUT clause lets you identify neatly which Names got which IDs.

而你想知道插入的ID,你運氣不好。您可以嘗試使用另一個SELECT找到它們,但是您需要另一個唯一列來甚至制定查詢,然后您遇到與上面的DELETE示例相同的問題。因此,OUTPUT子句可以讓您整齊地識別哪些名稱具有哪些ID。

You will need these IDs for example when creating dependent records with foreign keys. Think "Order" and "OrderDetails" which are linked by an OrderID column with an IDENTITY clause. Again, with a single INSERT you can get away with using SCOPE_IDENTITY() or @@IDENTITY, but when inserting multiple orders at once, you will need OUTPUT.

例如,在使用外鍵創建相關記錄時,您將需要這些ID。認為“Order”和“OrderDetails”由OrderID列與IDENTITY子句​​鏈接。同樣,使用單個INSERT,您可以使用SCOPE_IDENTITY()或@@ IDENTITY,但是當一次插入多個訂單時,您將需要OUTPUT。

#2


1  

When you perform Insert/Update/Delete operation on particular table and want to know what rows are affected OR want to log them for audit trail OR you want to use multiple values of affected rows in subsequent sql statements, you can use OUTPUT clause.

當您對特定表執行插入/更新/刪除操作並想知道哪些行受影響或想要將它們記錄為審計跟蹤時,或者您希望在后續sql語句中使用受影響行的多個值時,可以使用OUTPUT子句。

For Insert statement, it will have INSERTED table.

對於Insert語句,它將具有INSERTED表。

For Delete statement, it will have DELETED table. In case of Update DELETED table will contain rows (with old values) before update operation performed.

對於Delete語句,它將具有DELETED表。在更新的情況下,DELETED表將在執行更新操作之前包含行(具有舊值)。

For Update statement, it will have DELETED and INSERTED tables. DELETED table will contain rows (with old values) before update operation performed. INSERTED table will contain rows (with new values) after update operation performed.

對於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;

Now your query inserts rows in Production.ScrapReason as well as table variable @MyTableVar. Later it selects inserted rows from Production.ScrapReason and @MyTableVar. Thus you can compare both the resultset and it must have identical rows (considering Production.ScrapReason is empty table.)

現在,您的查詢在Production.ScrapReason中插入行以及表變量@MyTableVar。稍后它從Production.ScrapReason和@MyTableVar中選擇插入的行。因此,您可以比較結果集,並且它必須具有相同的行(考慮到Production.ScrapReason是空表。)

I hope it makes sense!

我希望它有意義!

Edit:

Inserted/Deleted tables will be available with Insert/Update/Delete statement and not after that. You may want to store those magic table values in db table or temp table.

插入/刪除表格將在插入/更新/刪除語句中提供,之后不會。您可能希望將這些魔術表值存儲在db table或temp table中。

#3


0  

Without the OUTPUT clause, how would you know which rows were deleted? Your example seems so simple because you already know the Id values, but what if you did this:

如果沒有OUTPUT子句,您如何知道刪除了哪些行?您的示例似乎很簡單,因為您已經知道了Id值,但是如果您這樣做會怎樣:

DELETE FROM T WHERE SomeColumn LIKE 'SomePattern%'

And you want to find out what was deleted. That's the purpose of the OUTPUT clause.

你想知道刪除了什么。這就是OUTPUT子句的目的。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2014/01/09/cdf6c0419c394dccbef59f0cf7488387.html



 
  © 2014-2022 ITdaan.com 联系我们: