TOP (Transact-SQL)
指定查询结果中将只返回第一组行。这组行可以是某一数量的行也可以是某一百分比数量的行。TOP 表达式可用在 SELECT、INSERT、UPDATE、MERGE 和 DELETE 语句中。
语法
[
TOP (expression) [PERCENT]
[ WITH TIES ]
]
参数
expression
指定返回行数的数值表达式。如果指定了 PERCENT,则 expression 将隐式转换为 float 值;否则,它将转换为 bigint。在 INSERT、UPDATE、MERGE 和 DELETE 语句中,需要使用括号来分隔 TOP 中的 expression。为保证向后兼容性,支持在 SELECT 使用不包含括号的 TOP expression,但不推荐这种用法。
如果查询包含 ORDER BY 子句,则将返回按 ORDER BY 子句排序的前 expression 行或 expression% 的行。如果查询没有 ORDER BY 子句,则行的顺序是随意的。
PERCENT
指示查询只返回结果集中前 expression % 的行。WITH TIES
指定从基本结果集中返回额外的行,对于 ORDER BY 列中指定的排序方式参数,这些额外的返回行的该参数值与 TOP n (PERCENT) 行中的最后一行的该参数值相同。只能在 SELECT 语句中且只有在指定了 ORDER BY 子句之后,才能指定 TOP...WITH TIES。注意 返回的记录关联顺序是任意的。ORDER BY 不影响此规则。
注释
在已分区视图中,不能将 TOP 与 UPDATE 和 DELETE 语句一起使用。
在与 INSERT、UPDATE、MERGE 或 DELETE 语句结合使用的 TOP 表达式中引用的行不按任何顺序排列。TOP n 随机返回 n 行。例如,下面的 INSERT 语句包含 ORDER BY 子句,但该子句并不影响由 INSERT 语句直接引用的行。
INSERT TOP (2) INTO Table2 (ColumnB)
SELECT ColumnA FROM Table1
ORDER BY ColumnA;
前一个查询中的 ORDER BY 子句仅引用嵌套 SELECT 语句返回的行。INSERT 语句选择 SELECT 语句返回的任意两行。若要确保插入 SELECT 子查询返回的前两行,请按如下所示重写该查询。
INSERT INTO Table2 (ColumnB)
SELECT TOP (2) ColumnA FROM Table1
ORDER BY ColumnA;
SQL Server 允许更新使用 TOP 子句创建的视图。由于 TOP 子句包含在视图定义中,所以如果更新后结果不再符合 TOP 表达式的要求,则可能导致某些行从视图中消失。有关详细信息,请参阅通过视图修改数据。
查询中的 TOP 表达式不影响由于触发器被激发而执行的语句。触发器中已插入和已更新的表中将只显示确实受 INSERT、UPDATE、MERGE 或 DELETE 语句影响的那些行。
在 MERGE 语句中使用 TOP
在 MERGE 语句中指定 TOP 子句时,会在对整个源表和整个目标表进行联接且删除了不符合插入、更新或删除操作条件的联接行之后应用该子句。TOP 子句将联接行的数量进一步减少为指定值,并且以一种无序方式对其余联接行应用插入、更新或删除操作。也就是说,在 WHEN 子句中定义的操作中,这些行是无序分布的。例如,如果指定 TOP (10),将会影响 10 行;在这些行中,可能会更新 7 行而插入 3 行,或者可能删除 1 行、更新 5 行并且插入 4 行,等等。
由于 MERGE 语句对源表和目标表都进行完全表扫描,因此在使用 TOP 子句通过创建多个批处理来修改大型表时,I/O 性能可能会受到影响。在这种情况下,一定要确保所有连续批处理都以新行作为处理目标。有关详细信息,请参阅优化 MERGE 语句性能。
示例
A. 在 TOP 中使用变量
以下示例使用变量获取 AdventureWorks 数据库的 dbo.Employee 表中列出的前 10 个雇员。
USE AdventureWorks;
GO
DECLARE @p AS int;
SELECT @p=10
SELECT TOP(@p)*
FROM HumanResources.Employee;
GO
B. 在 TOP 中使用 PERCENT 和 WITH TIES
以下示例获取所有雇员中薪金最高的 10 个百分比的雇员,并根据基本薪金按降序返回。指定 WITH TIES 可确保结果集中同时包含其薪金与返回的最低薪金相同的所有雇员,即使这样做会超过雇员总数的 10 个百分比。
USE AdventureWorks;
GO
SELECT TOP(10) PERCENT WITH TIES
c.FirstName, c.LastName, e.Title, e.Gender, r.Rate
FROM Person.Contact AS c
INNER JOIN HumanResources.Employee AS e
ON c.ContactID = e.ContactID
INNER JOIN HumanResources.EmployeePayHistory AS r
ON r.EmployeeID = e.EmployeeID
ORDER BY Rate DESC;