SQL Server 2005 引入 OUTPUT 子句,允許在 INSERT、UPDATE、DELETE、MERGE 陳述式中直接存取 inserted、deleted 虛擬資料表,無需額外查詢即可取得身分識別欄位、預設值、計算欄位等伺服器端產生的值。本文以 UNIQUEIDENTIFIER + NEWID() 為例示範。
INSERT INTO target_table (columns...)
OUTPUT inserted.column_list
VALUES (...)
-- 或
INSERT INTO target_table (columns...)
OUTPUT inserted.column_list
SELECT ... FROM source_table
DECLARE @t TABLE (
id UNIQUEIDENTIFIER DEFAULT NEWID(),
name VARCHAR(100)
);
INSERT INTO @t (name)
OUTPUT inserted.id
SELECT 'jinjazz' UNION ALL SELECT 'sqlserver';
id
------------------------------------
3880DB77-5ADF-472D-A68D-7518DD76F3B8
F478A3F5-A501-404E-A328-372EEC26279D
DECLARE @Orders TABLE (
OrderID INT IDENTITY(1,1) PRIMARY KEY,
OrderGUID UNIQUEIDENTIFIER DEFAULT NEWSEQUENTIALID(),
OrderDate DATETIME DEFAULT GETDATE(),
CustomerID INT,
Amount MONEY
);
INSERT INTO @Orders (CustomerID, Amount)
OUTPUT inserted.OrderID, inserted.OrderGUID, inserted.OrderDate
VALUES (1001, 1250.00), (1002, 890.50), (1003, 2100.00);
DECLARE @Audit TABLE (OrderID INT, OrderGUID UNIQUEIDENTIFIER, ActionTime DATETIME);
INSERT INTO @Orders (CustomerID, Amount)
OUTPUT inserted.OrderID, inserted.OrderGUID, GETDATE() INTO @Audit
VALUES (1004, 500.00);
UPDATE @Orders
SET Amount = Amount * 1.1
OUTPUT deleted.OrderID, deleted.Amount AS OldAmount, inserted.Amount AS NewAmount
WHERE CustomerID = 1001;
DELETE FROM @Orders
OUTPUT deleted.* INTO @DeletedOrdersArchive
WHERE OrderDate < '2020-01-01';
| 特性 | OUTPUT 子句 | SCOPE_IDENTITY() | @@IDENTITY |
|---|---|---|---|
| 支援多筆資料列 | ✓ | ✗ (僅單筆) | ✗ |
| 可取得非 IDENTITY 欄位 (GUID、DEFAULT、Computed) | ✓ | ✗ | ✗ |
| 可導入資料表/變數 | ✓ | ✗ | ✗ |
| 觸發器安全 | ✓ | ✓ | ✗ (觸發器插入會干擾) |
| 適用陳述式 | INSERT/UPDATE/DELETE/MERGE | INSERT | INSERT |
OUTPUT 不支援參考 text、ntext、image、xml (大型值型別) 欄位,需改用 OUTPUT ... INTO 搭配暫存表OUTPUT 的 DML 陳述式不可用於 VIEW (除非搭配 INSTEAD OF 觸發器)OUTPUT 結果順序不保證與輸入順序一致,需自行加 ROW_NUMBER() 對應-- 1. 習慣用 OUTPUT 取代 SCOPE_IDENTITY(),尤其批次作業
-- 2. 稽核欄位直接用 OUTPUT INTO 寫入稽核表,避免觸發器效能負擔
-- 3. MERGE 陳述式搭配 OUTPUT $action, inserted.*, deleted.* 可完整記錄增刪改
-- 4. 搭配 TRY...CATCH 確保交易一致性