http://www.cnblogs.com/yuananyun/archive/2010/12/04/1896276.html
一、关于output子句
SQL Server 2005中的output子句,可以使你从修改语句(INSERT、UPDATE、DELETE)中将数据返回到表变量中。带结果的 DML 的有用方案包括清除和存档、消息处理应用程序以及其他方案。这一新的 OUTPUT 子句的语法为:
OUTPUT INTO @table_variable
可以通过引用插入的表和删除的表来访问被修改的行的旧/新映像,其方式与访问触发器类似。在 INSERT 语句中,只能访问插入的表。在 DELETE 语句中,只能访问删除的表。在 UPDATE 语句中,可以访问插入的表和删除的表。
二、实例说明
1、将 OUTPUT INTO 用于简单 INSERT 语句
以下示例将行插入 ScrapReason 表,并使用 OUTPUT 子句将语句的结果返回到 @MyTableVar table 变量。由于 ScrapReasonID 列使用 IDENTITY 属性定义,因此未在 INSERT 语句中为该列指定一个值。但请注意,将在列 INSERTED.ScrapReasonID 内的 OUTPUT 子句中返回由数据库引擎 为该列生成的值。
use
AdventureWorks
go
--
定义一个表格变量
declare
@mytablevar
table
( ScrapReasonID
smallint
, Name1
varchar
(
50
), ModifiedDate
datetime
)
insert
into
Production.ScrapReason output inserted.ScrapReasonID,inserted.
[
Name
]
,inserted.ModifiedDate
into
@mytablevar
values
(
'
operator error
'
,
getdate
());
--
显示@mytablevar中的数据
select
*
from
@mytablevar
--
显示Production.ScrapReason表中的数据
select
*
from
Production.ScrapReason
go
以上语句中inserted是一个临时表,当我们往数据表中插入一条数据的时候数据库会创建一个临时表inserted保存插入的记录;当我们删除某条记录的时候,数据库会创建一个临时表deleted保存删除的记录。以上语句把新插入的数据填充到表变量@mytablevar中,然后输出数据,可以看到@mytablevar中的记录和Production.ScrapReason中新插入的数据是一样的。
2、 将 OUTPUT 用于 INSERT…SELECT 语句
以下示例创建 EmployeeSales 表,然后通过使用 SELECT 语句检索源表中的数据将几行插入该表。同时,也计算了列 ProjectedSales 的值并将其插入该表中。OUTPUT 子句将 INSERT 语句的结果返回到执行调用的应用程序。最后的 SELECT 语句验证新 EmployeeSales 表的内容是否与 OUTPUT 子句的结果匹配。
use
AdventureWorks
go
if
object_id
(
'
dbo.EmployeeSales
'
,
'
u
'
)
is
not
null
drop
table
dbo.EmployeeSales
go
create
table
dbo.EmployeeSales ( EmployeeID
nvarchar
(
11
)
not
null
, LastName
nvarchar
(
20
)
not
null
, FirstName
nvarchar
(
20
)
not
null
, CurrentSales
money
not
null
, ProjectedSales
money
not
null
)
go
insert
into
dbo.EmployeeSales output inserted.EmployeeID,inserted.LastName,inserted.FirstName,inserted.CurrentSales,inserted.ProjectedSales
SELECT
e.EmployeeID, c.LastName, c.FirstName, sp.SalesYTD, sp.SalesYTD
*
1.10
FROM
HumanResources.Employee
AS
e
INNER
JOIN
Sales.SalesPerson
AS
sp
ON
e.EmployeeID
=
sp.SalesPersonID
INNER
JOIN
Person.Contact
AS
c
ON
e.ContactID
=
c.ContactID
WHERE
e.EmployeeID
LIKE
'
2%
'
ORDER
BY
c.LastName, c.FirstName;
GO
SELECT
EmployeeID, LastName, FirstName, CurrentSales, ProjectedSales
FROM
dbo.EmployeeSales;
GO
3、 将 OUTPUT 用于 DELETE 语句
以下示例将删除 ShoppingCartItem 表中的所有行。子句 OUTPUT DELETED.* 指定 DELETE 语句的结果(即已删除的行中的所有列)返回到执行调用的应用程序。后面的 SELECT 语句验证对 ShoppingCartItem 表所执行的删除操作的结果。
USE
AdventureWorks;
GO
DELETE
Sales.ShoppingCartItem OUTPUT DELETED.
*
;
--
验证表中所有数据都被删除
SELECT
COUNT
(
*
)
AS
[
Rows in Table
]
FROM
Sales.ShoppingCartItem;
GO
4、 将 OUTPUT INTO 用于 UPDATE
下面的示例将 Employee 表中 VacationHours 列的前 10 行更新 25%。OUTPUT 子句将返回 VacationHours 值,该值在将列 DELETED.VacationHours 中的 UPDATE 语句和列 INSERTED.VacationHours 中的已更新值应用于 @MyTableVar table 变量之前存在。
在它后面的两个 SELECT 语句返回 @MyTableVar 中的值以及 Employee 表中更新操作的结果。请注意,INSERTED.ModifiedDate 列中的结果与 Employee 表中的 ModifiedDate 列不具有相同的值。这是因为对 Employee 表定义了将 ModifiedDate 的值更新为当前日期的 AFTER UPDATE 触发器。但是,从 OUTPUT 中返回的列反映触发器激发之前的数据。
USE
AdventureWorks;
GO
DECLARE
@MyTableVar
table
( EmpID
int
NOT
NULL
, OldVacationHours
int
, NewVacationHours
int
, ModifiedDate
datetime
);
UPDATE
TOP
(
10
) HumanResources.Employee
SET
VacationHours
=
VacationHours
*
1.25
OUTPUT INSERTED.EmployeeID, DELETED.VacationHours, INSERTED.VacationHours, INSERTED.ModifiedDate
INTO
@MyTableVar
;
--
显示@MyTableVar的值
SELECT
EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM
@MyTableVar
;
GO
--
显示插入表的值
SELECT
TOP
(
10
) EmployeeID, VacationHours, ModifiedDate
FROM
HumanResources.Employee;
GO
5、 使用 OUTPUT INTO 返回表达式
以下示例在示例 D 的基础上生成,方法是通过将 OUTPUT 子句中的表达式定义为已更新的 VacationHours 值与应用更新之前的 VacationHours 值之间的差异。该表达式的值返回到列 VacationHoursDifference 中的 @MyTableVar table 变量。
USE
AdventureWorks;
GO
DECLARE
@MyTableVar
table
( EmpID
int
NOT
NULL
, OldVacationHours
int
, NewVacationHours
int
, VacationHoursDifference
int
, ModifiedDate
datetime
);
UPDATE
TOP
(
10
) HumanResources.Employee
SET
VacationHours
=
VacationHours
*
1.25
OUTPUT INSERTED.EmployeeID, DELETED.VacationHours, INSERTED.VacationHours, INSERTED.VacationHours
-
DELETED.VacationHours, INSERTED.ModifiedDate
INTO
@MyTableVar
;
--
显示表变量中的数据
SELECT
EmpID, OldVacationHours, NewVacationHours, VacationHoursDifference, ModifiedDate
FROM
@MyTableVar
;
GO
SELECT
TOP
(
10
) EmployeeID, VacationHours, ModifiedDate
FROM
HumanResources.Employee;
GO
6、 在 UPDATE 语句中使用包含 from_table_name 的 OUTPUT INTO
以下示例使用指定的 ProductID 和 ScrapReasonID,针对 WorkOrder 表中的所有工作顺序更新 ScrapReasonID 列。OUTPUT INTO 子句返回所更新表 (WorkOrder) 中的值以及 Product 表中的值。在 FROM 子句中使用 Product 表来指定要更新的行。由于 WorkOrder 表具有对其定义的 AFTER UPDATE 触发器,因此需要 INTO 关键字。
USE
AdventureWorks;
GO
DECLARE
@MyTestVar
table
( OldScrapReasonID
int
NOT
NULL
, NewScrapReasonID
int
NOT
NULL
, WorkOrderID
int
NOT
NULL
, ProductID
int
NOT
NULL
, ProductName
nvarchar
(
50
)
NOT
NULL
);
UPDATE
Production.WorkOrder
SET
ScrapReasonID
=
4
OUTPUT DELETED.ScrapReasonID, INSERTED.ScrapReasonID, INSERTED.WorkOrderID, INSERTED.ProductID, p.Name
INTO
@MyTestVar
FROM
Production.WorkOrder
AS
wo
INNER
JOIN
Production.Product
AS
p
ON
wo.ProductID
=
p.ProductID
AND
wo.ScrapReasonID
=
16
AND
p.ProductID
=
733
;
SELECT
OldScrapReasonID, NewScrapReasonID, WorkOrderID, ProductID, ProductName
FROM
@MyTestVar
;
GO
7、在 DELETE 语句中使用包含 from_table_name 的 OUTPUT INTO
以下示例将按照在 DELETE 语句的 FROM 子句中所定义的搜索条件删除 ProductProductPhoto 表中的行。OUTPUT 子句返回所删除表(DELETED.ProductID、DELETED.ProductPhotoID)中的列以及 Product 表中的列。在 FROM 子句中使用该表来指定要删除的行。
USE
AdventureWorks
GO
DECLARE
@MyTableVar
table
( ProductID
int
NOT
NULL
, ProductName
nvarchar
(
50
)
NOT
NULL
, ProductModelID
int
NOT
NULL
, PhotoID
int
NOT
NULL
);
DELETE
Production.ProductProductPhoto OUTPUT DELETED.ProductID, p.Name, p.ProductModelID, DELETED.ProductPhotoID
INTO
@MyTableVar
FROM
Production.ProductProductPhoto
AS
ph
JOIN
Production.Product
as
p
ON
ph.ProductID
=
p.ProductID
WHERE
p.ProductModelID
BETWEEN
120
and
130
;
SELECT
ProductID, ProductName, ProductModelID, PhotoID
FROM
@MyTableVar
ORDER
BY
ProductModelID;
GO
8、 将 OUTPUT INTO 用于大型对象数据类型s
以下示例使用 .WRITE 子句更新 Production.Document 表内 DocumentSummary 这一 nvarchar(max) 列中的部分值。通过指定替换单词、现有数据中要替换的单词的开始位置(偏移量)以及要替换的字符数(长度),将单词 components 替换为单词 features。此示例使用 OUTPUT 子句将 DocumentSummary 列的前像和后像返回到 @MyTableVar table 变量。请注意,将返回 DocumentSummary 列的全部前像和后像。
USE
AdventureWorks;
GO
DECLARE
@MyTableVar
table
( DocumentID
int
NOT
NULL
, SummaryBefore
nvarchar
(
max
), SummaryAfter
nvarchar
(
max
));
UPDATE
Production.Document
SET
DocumentSummary .WRITE (N
'
features
'
,
28
,
10
) OUTPUT INSERTED.DocumentID, DELETED.DocumentSummary, INSERTED.DocumentSummary
INTO
@MyTableVar
WHERE
DocumentID
=
3
;
SELECT
DocumentID, SummaryBefore, SummaryAfter
FROM
@MyTableVar
;
GO
9、 在 INSTEAD OF 触发器中使用 OUTPUT
以下示例在触发器中使用 OUTPUT 子句返回触发器操作的结果。首先,创建一个 ScrapReason 表的视图,然后对该视图定义 INSTEAD OF INSERT 触发器,从而使用户只修改基表的 Name 列。由于列 ScrapReasonID 是基表中的 IDENTITY 列,因此触发器将忽略用户提供的值。这允许数据库引擎 自动生成正确的值。同样,用户为 ModifiedDate 提供的值也被忽略并设置为正确的日期。OUTPUT 子句返回实际插入 ScrapReason 表中的值。
UUSE AdventureWorks;
GO
IF
OBJECT_ID
(
'
dbo.vw_ScrapReason
'
,
'
V
'
)
IS
NOT
NULL
DROP
VIEW
dbo.vw_ScrapReason;
GO
CREATE
VIEW
dbo.vw_ScrapReason
AS
(
SELECT
ScrapReasonID, Name, ModifiedDate
FROM
Production.ScrapReason);
GO
CREATE
TRIGGER
dbo.io_ScrapReason
ON
dbo.vw_ScrapReason INSTEAD
OF
INSERT
AS
BEGIN
--
ScrapReasonID is not specified in the list of columns to be inserted
--
because it is an IDENTITY column.
INSERT
INTO
Production.ScrapReason (Name, ModifiedDate) OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
SELECT
Name,
getdate
()
FROM
inserted;
END
GO
INSERT
vw_ScrapReason (ScrapReasonID, Name, ModifiedDate)
VALUES
(
99
, N
'
My scrap reason
'
,
'
20030404
'
);
GO
10、 将 OUTPUT INTO 用于标识列和计算列
下面的示例创建 EmployeeSales 表,然后使用 INSERT 语句向其中插入若干行,并使用 SELECT 语句从源表中检索数据。EmployeeSales 表包含标识列 (EmployeeID) 和计算列 (ProjectedSales)。由于这些值是在插入操作期间由数据库引擎生成的,因此,不能在 @MyTableVar 中定义上述两列。
USE
AdventureWorks ;
GO
IF
OBJECT_ID
(
'
dbo.EmployeeSales
'
,
'
U
'
)
IS
NOT
NULL
DROP
TABLE
dbo.EmployeeSales;
GO
CREATE
TABLE
dbo.EmployeeSales ( EmployeeID
int
IDENTITY
(
1
,
5
)
NOT
NULL
, LastName
nvarchar
(
20
)
NOT
NULL
, FirstName
nvarchar
(
20
)
NOT
NULL
, CurrentSales
money
NOT
NULL
, ProjectedSales
AS
CurrentSales
*
1.10
);
GO
DECLARE
@MyTableVar
table
( LastName
nvarchar
(
20
)
NOT
NULL
, FirstName
nvarchar
(
20
)
NOT
NULL
, CurrentSales
money
NOT
NULL
);
INSERT
INTO
dbo.EmployeeSales (LastName, FirstName, CurrentSales) OUTPUT INSERTED.LastName, INSERTED.FirstName, INSERTED.CurrentSales
INTO
@MyTableVar
SELECT
c.LastName, c.FirstName, sp.SalesYTD
FROM
HumanResources.Employee
AS
e
INNER
JOIN
Sales.SalesPerson
AS
sp
ON
e.EmployeeID
=
sp.SalesPersonID
INNER
JOIN
Person.Contact
AS
c
ON
e.ContactID
=
c.ContactID
WHERE
e.EmployeeID
LIKE
'
2%
'
ORDER
BY
c.LastName, c.FirstName;
SELECT
LastName, FirstName, CurrentSales
FROM
@MyTableVar
;
GO
SELECT
EmployeeID, LastName, FirstName, CurrentSales, ProjectedSales
FROM
dbo.EmployeeSales;
GO