现在可以在 DELETE、UPDATE 和 INSERT 查询中使用 TOP 选项。
使用 TOP 选项的查询的新语法是:
SELECT [TOP () [PERCENT] [WITH TIES]]
FROM [ORDER BY]
DELETE [TOP () [PERCENT]] FROM
UPDATE [TOP () [PERCENT]] SET
INSERT [TOP () [PERCENT]] INTO
必须在括号中指定数字表达式。在 SELECT 查询中支持不用括号指定常量的原因是为了保持向后兼容。表达式必须是独立的 — 如果您使用子查询,则它无法引用外部查询中的表的列。如果您不指定 PERCENT 选项,则该表达式必须可以隐式转换为 bigint 数据类型。如果您指定 PERCENT 选项,则该表达式必须可以隐式转换为 float 并且落在范围 0 到 100 之内。WITH TIES 选项和 ORDER BY 子句只在 SELECT 查询中受到支持。
例如,以下代码使用变量作为 TOP 选项的参数,并且返回指定数量的最新购买定单:
USE AdventureWorks
DECLARE @n AS BIGINT
SET @n = 2
SELECT TOP(@n) *
FROM Purchasing.PurchaseOrderHeader
ORDER BY OrderDate DESC
当您将所请求的行的数量作为存储过程或用户定义函数的参数时,该增强功能尤其有用。通过使用独立的子查询,您可以回答动态请求,例如,“计算每月定单的平均数量,并返回那么多的最新定单”:
USE AdventureWorks
SELECT TOP(SELECT
COUNT(*)/DATEDIFF(month, MIN(OrderDate), MAX(OrderDate))
FROM Purchasing.PurchaseOrderHeader) *
FROM Purchasing.PurchaseOrderHeader
ORDER BY OrderDate DESC
较低版本的 SQL Server 中的 SET ROWCOUNT 选项使您可以限制受到查询影响的行数。例如,SET ROWCOUNT 常用来定期清除多个小型事务而不是单个大型事务中的大量数据:
SET ROWCOUNT 1000
DELETE FROM BigTable WHERE datetimecol < ''20000101''
WHILE @@rowcount > 0
DELETE FROM BigTable WHERE datetimecol < ''20000101''
SET ROWCOUNT 0
以该方式使用 SET ROWCOUNT,可以在清除过程中备份和回收事务日志,并且还可以防止锁升级。现在可以这样使用 TOP,而不是使用 SET ROWCOUNT:
DELETE TOP(1000) FROM BigTable WHERE datetimecol < ''20000101''
WHILE @@rowcount > 0
DELETE TOP(1000) FROM BigTable WHERE datetimecol < ''20000101''
当您使用 TOP 选项时,优化程序可以知道“行目标”是什么以及到底是否使用了 TOP,从而使优化程序可以产生更有效的计划。
尽管您可能认为不需要在 INSERT 语句中使用 TOP(因为您总是可以在 SELECT 查询中指定它),但您可能会发现它在插入 EXEC 命令的结果或 UNION 操作的结果时很有用。例如:
INSERT TOP INTO
EXEC
INSERT TOP INTO
SELECT FROM T1
UNION ALL
SELECT FROM T2
ORDER BY
带结果的 DML
SQL Server 2005 引入了一个新的 OUTPUT 子句,以使您可以从修改语句(INSERT、UPDATE、DELETE)中将数据返回到表变量中。带结果的 DML 的有用方案包括清除和存档、消息处理应用程序以及其他方案。这一新的 OUTPUT 子句的语法为:
OUTPUT <dml_select_list> INTO @table_variable
可以通过引用插入的表和删除的表来访问被修改的行的旧/新映像,其方式与访问触发器类似。在 INSERT 语句中,只能访问插入的表。在 DELETE 语句中,只能访问删除的表。在 UPDATE 语句中,可以访问插入的表和删除的表。
作为带结果的 DML 可能有用的清除和存档方案的示例,假设您具有一个大型的 Orders 表,并且您希望定期清除历史数据。您还希望将清除的数据复制到一个名为 OrdersArchive 的存档表中。您声明了一个名为 @DeletedOrders 的表变量,并且进入一个循环,在该循环中,您使用上文中的“TOP 增强功能”一节中描述的清除方法,成块地删