SQL Server 2005 引入 OUTPUT 子句,讓 DML 陳述式(INSERT/UPDATE/DELETE)**在同一個原子操作中**回傳受影響的資料列(含身分識別欄位、計算欄位、預設值、觸發器修改後的值),免去 SCOPE_IDENTITY()、@@IDENTITY、觸發器、暫存表等繞彎做法。
-- INSERT
INSERT target_table (cols)
OUTPUT inserted.col1, inserted.col2 INTO @TableVar
SELECT ... FROM source;
-- UPDATE
UPDATE target_table
SET col = value
OUTPUT inserted.*, deleted.* INTO @TableVar
WHERE ...;
-- DELETE
DELETE target_table
OUTPUT deleted.* INTO @TableVar
WHERE ...;
inserted:新值(INSERT/UPDATE)deleted:舊值(UPDATE/DELETE)INTO @TableVar:導向表變數/實體表(選用,省略則直接回傳用戶端)IF OBJECT_ID('ta') IS NOT NULL DROP TABLE ta;
CREATE TABLE ta (ID INT IDENTITY, [name] VARCHAR(10));
INSERT ta([name]) VALUES ('a'),('b'),('c'),('d'),('e'),('f'),('g');
IF OBJECT_ID('tb') IS NOT NULL DROP TABLE tb;
CREATE TABLE tb (ID INT IDENTITY, [name] VARCHAR(10));
INSERT tb([name]) VALUES ('a'),('b'),('c');
DECLARE @t TABLE (ID INT, [name] VARCHAR(10));
INSERT tb
OUTPUT inserted.ID, inserted.[name] INTO @t
SELECT [name] FROM ta
WHERE NOT EXISTS (SELECT 1 FROM tb WHERE [name] = ta.[name]);
SELECT * FROM @t;
-- 結果: ID=4~7, name=d,e,f,g
DELETE tb OUTPUT deleted.* WHERE ID = 9;
-- 直接在結果格網顯示被刪除的列
UPDATE tb SET [name] = 'test'
OUTPUT inserted.*, deleted.*
WHERE ID = 10;
-- inserted: 新值 (10, 'test')
-- deleted: 舊值 (10, 'f')
MERGE tb AS target
USING (SELECT [name] FROM ta) AS src
ON target.[name] = src.[name]
WHEN NOT MATCHED THEN
INSERT ([name]) VALUES (src.[name])
WHEN MATCHED THEN
UPDATE SET target.[name] = src.[name] -- 示意
OUTPUT $action, inserted.*, deleted.*;
BEGIN TRY
BEGIN TRAN;
DELETE tb OUTPUT deleted.ID, deleted.[name], GETDATE(), 'DELETE'
INTO AuditLog (EntityID, EntityName, ChangeTime, Operation)
WHERE [name] > 'c';
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK; THROW;
END CATCH
| 限制 | 說明 |
|---|---|
| 參考本地/分散式分區檢視、遠端資料表 | 不支援 OUTPUT |
| INSERT ... EXEC | 不支援 OUTPUT |
| OUTPUT INTO 目標為檢視/資料列集函數 | 不支援 |
| 觸發器內部的 OUTPUT | 行為特殊,需實測 |
| 大型物件類型 | text/ntext/image 不可直接 OUTPUT,需轉 varchar(max)/varbinary(max) |