SQL SERVER 2005中全新的OUTPUT子句添加數據記錄詳解(理論篇)

也許大家在數據庫開發的時候,會發現這樣一個現象:添加數據記錄後想查看其結果都必須通過select表達式來查詢實現。一定都要多此一舉纔可以看到被添加的數據記錄嗎?答案是否定的。SQL SERVER 2005新提供的OUTPUT子句就幫您解決這個難題,它以比觸發器更簡潔的方式,在添加數據記錄的同時或者事後顯示所添加的數據記錄內容。下面是作者通過查找幫助文檔MSDN和章立民老師的《SQL Server 2005數據庫開發實戰》等資料後總結如下:

理論篇

OUTPUT子句返回受 INSERT、UPDATE 或 DELETE 語句影響的每行的信息,或者返回基於上述每行的表達式。這些結果可以返回到處理應用程序,以供在確認消息、存檔以及其他類似的應用程序要求中使用。此外,也可以將結果插入表或表變量。

用於:

DELETE

INSERT

UPDATE

 Transact-SQL 語法約定

語法

 
<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 }

備註

OUTPUT <dml_select_list> 子句和 OUTPUT <dml_select_list> INTO { @table_variable | output_table } 子句可以在單個 INSERT、UPDATE 或 DELETE 語句中定義。

注意:
除非另行指定,否則,對 OUTPUT 子句的引用將同時引用 OUTPUT 子句和 OUTPUT INTO 子句。

 

 

OUTPUT 子句對於在 INSERT 或 UPDATE 操作之後檢索標識列或計算列的值可能非常有用。

當 <dml_select_list> 中包含計算列時,輸出表或表變量中的相應列並不是計算列。新列中的值是在執行該語句時計算出的值。

以下語句中不支持 OUTPUT 子句:

  • 引用本地分區視圖、分佈式分區視圖或遠程表的 DML 語句。
  • 包含 EXECUTE 語句的 INSERT 語句。

不能將 OUTPUT INTO 子句插入視圖或行集函數。

無法保證將更改應用於表的順序與將行插入輸出表或表變量的順序相對應。

如果將參數或變量作爲 UPDATE 語句的一部分進行了修改,則 OUTPUT 子句將始終返回語句執行之前的參數或變量的值而不是已修改的值。

在使用 WHERE CURRENT OF 語法通過遊標定位的 UPDATE 或 DELETE 語句中,可以使用 OUTPUT。

觸發器

從 OUTPUT 中返回的列反映 INSERT、UPDATE 或 DELETE 語句完成之後但在觸發器執行之前的數據。

對於 INSTEAD OF 觸發器,即使沒有因爲觸發器的操作而發生修改,也會如同實際執行 INSERT、UPDATE 或 DELETE 那樣生成返回的結果。如果在觸發器的主體內使用包含 OUTPUT 子句的語句,則必須使用表別名來引用觸發器 inserted 和 deleted 表,以免使用與 OUTPUT 關聯的 INSERTED 和 DELETED 表複製列引用。

如果指定了 OUTPUT 子句但未同時指定 INTO 關鍵字,則對於給定的 DML 操作,DML 操作的目標不能啓用對其定義的任何觸發器。例如,如果在 UPDATE 語句中定義了 OUTPUT 子句,則目標表不能具有任何啓用的 UPDATE 觸發器。

如果設置了 sp_configure 選項 disallow results from triggers,則從觸發器內調用語句時,不帶 INTO 子句的 OUTPUT 子句將導致該語句失敗。

數據類型

OUTPUT 子句支持下列大型對象數據類型:nvarchar(max)、varchar(max)、varbinary(max)、 text、ntext、image 和 xml。當在 UPDATE 語句中使用 .WRITE 子句修改 nvarchar(max)、varchar(max) 或 varbinary(max) 列時,如果引用了值的全部前像和後像,則將其返回。在 OUTPUT 子句中,TEXTPTR( ) 函數不能作爲 text、ntext 或 image 列的表達式的一部分出現。

隊列

可以在將表用作隊列或將表用於保持中間結果集的應用程序中使用 OUTPUT。換句話說,應用程序不斷地在表中添加或刪除行。以下示例在 DELETE 語句中使用 OUTPUT 子句將已刪除的行返回到執行調用的應用程序。

 複製代碼
USE AdventureWorks;
GO
DELETE TOP(1) dbo.DatabaseLog WITH (READPAST)
OUTPUT deleted.*
WHERE DatabaseLogID = 7;
GO

此示例從用作隊列的表中刪除一行,並使用單個操作將已刪除的值返回到處理應用程序。還可實現其他語義,例如使用表來實現堆棧。但是,SQL Server 並不保證由使用 OUTPUT 子句的 DML 語句處理和返回行的順序。應用程序負責包括可保證所需語義的適當 WHERE 子句,或者理解當針對 DML 操作可能限定多行時,沒有保證的順序。以下示例使用子查詢,並假定 DatabaseLogID 列具有唯一性特徵才能實現所需的排序語義。

 複製代碼
USE AdventureWorks;
GO
DELETE dbo.DatabaseLog
OUTPUT deleted.*
WHERE DatabaseLogID IN (SELECT TOP(5) DatabaseLogID FROM dbo.DatabaseLog ORDER BY PostTime);
GO
注意:
如果您的方案允許多個應用程序從一個表中執行析構性讀取,請在 UPDATE 和 DELETE 語句中使用 READPAST 表提示。這可防止在其他應用程序已經讀取表中第一個限定記錄的情況下出現鎖定問題。

 

 

參數

@table_variable

指定一個 table 變量,返回的行將插入該變量中而不是返回到調用方。@table_variable 必須在 INSERT、UPDATE 或 DELETE 語句之前聲明。

如果未指定 column_list,則 table 變量必須與 OUTPUT 結果集具有相同的列數。標識列和計算列除外,這兩種列必須跳過。如果指定了 column_list,則任何省略的列都必須允許空值,或者都分配有默認值。

 

output_table

指定一個表,返回的行將被插入該表中而不是返回到調用方。output_table 可以爲臨時表。

如果未指定 column_list,則表必須與 OUTPUT 結果集具有相同的列數。標識列和計算列例外,必須跳過這兩種列。如果指定了 column_list,則任何省略的列都必須允許空值,或者都分配有默認值。

output_table 無法應用於以下情況:

  • 具有啓用的對其定義的觸發器。
  • 參與到外鍵約束雙方的任意一方。
  • 具有 CHECK 約束或啓用的規則。
column_list

INTO 子句目標表上列名的可選列表。它類似於 INSERT 語句中允許使用的列列表。

scalar_expression

可取計算結果爲單個值的任何符號和運算符的組合。只要子查詢返回單個值,便可使用子查詢。scalar_expression 中不允許使用聚合函數。

對修改的表中的列的任何引用都必須使用 INSERTED 或 DELETED 前綴限定。

column_alias_identifier

用於引用列名的替代名稱。

DELETED

指定由更新或刪除操作刪除的值的列前綴。以 DELETED 爲前綴的列反映 UPDATE 或 DELETE 語句完成之前的值。

不能在 INSERT 語句中同時使用 DELETED 與 OUTPUT 子句。

INSERTED

列的前綴,指定由插入操作或更新操作添加的值。以 INSERTED 爲前綴的列反映 UPDATE 或 INSERT 語句完成之後但在觸發器執行之前的值。

INSERTED 語句不能與 DELETE 語句的 OUTPUT 子句同時使用。

from_table_name

列的前綴,指定 DELETE 語句或 UPDATE 語句(用於指定要更新或刪除的行)的 FROM 子句中所包含的表。

如果還在 FROM 子句中指定了要修改的表,則對該表中的列的任何引用都必須使用 INSERTED 或 DELETED 前綴限定。

*

指定受刪除、插入或更新操作影響的所有列都將按照它們在表中的順序返回。

例如,以下 DELETE 語句中的 OUTPUT DELETED.* 將返回 ShoppingCartItem 表中所有已刪除的列:

 複製代碼
DELETE Sales.ShoppingCartItem
    OUTPUT DELETED.*;
column_name

顯式列引用。任何對修改的表的引用都必須使用相應的 INSERTED 或 DELETED 前綴正確限定,例如:INSERTED.column_name。

權限

要求對通過 <dml_select_list> 檢索的任何列或者在 <scalar_expression> 中使用的任何列具有 SELECT 權限。

要求對 <output_table> 中指定的任何表具有 INSERT 權限。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章