DATABASE

SQL Server 2008 : Transact-SQL Programming - TOP Enhancements

5/24/2011 4:00:33 PM
The TOP clause allows you to specify the number or percentage of rows to be returned by a SELECT statement. SQL Server 2005 introduced the capability for the TOP clause to also be used in INSERT, UPDATE, and DELETE statements. The syntax was also enhanced to allow the use of a numeric expression for the number value rather than having to use a hard-coded number.

The syntax for the TOP clause is as follows:

SELECT [TOP (numeric_expression) [PERCENT] [WITH TIES]]
FROM table_name ...[ORDER BY...]
DELETE [TOP (numeric_expression) [PERCENT]] FROM table_name ...
UPDATE [TOP (numeric_expression) [PERCENT]] table_name SET ...
INSERT [TOP (numeric_expression) [PERCENT]] INTO table_name ...

numeric_expression must be specified in parentheses. Specifying constants without parentheses is supported in SELECT queries only for backward compatibility. The parentheses around the expression are always required when TOP is used in UPDATE, INSERT, or DELETE statements.

If you do not specify the PERCENT option, the numeric expression must be implicitly convertible to the bigint data type. If you specify the PERCENT option, the numeric expression must be implicitly convertible to float and fall within the range of 0 to 100. The WITH TIES option with the ORDER BY clause is supported only with SELECT statements.

The following example shows the use of a local variable as the numeric expression for the TOP clause to limit the number of rows returned by a SELECT statement:

declare @rows int
select @rows = 5
select top (@rows) * from sales
go

stor_id ord_num ord_date qty payterms title_id
------- -------------------- ----------------------- ------ ------------ --------
6380 6871 2007-09-14 00:00:00.000 5 Net 60 BU1032
6380 722a 2007-09-13 00:00:00.000 3 Net 60 PS2091
6380 ONFFFFFFFFFFFFFFFFFF 2007-08-09 00:00:00.000 852 Net 30 FI1980
7066 A2976 2006-05-24 00:00:00.000 50 Net 30 PC8888
7066 ONAAAAAAAAAA 2007-01-13 00:00:00.000 948 Net 60 CH2480



Allowing the use of a numeric expression rather than a constant for the TOP command is especially useful when the number of requested rows is passed as a parameter to a stored procedure or function. When you use a subquery as the numeric expression, it must be self-contained; it cannot refer to columns of a table in the outer query. Using a self-contained subquery allows you to more easily develop queries for dynamic requests, such as “calculate the average number of titles published per week and return that many titles which were most recently published”:

SELECT TOP(SELECT COUNT(*)/DATEDIFF(month, MIN(pubdate), MAX(pubdate))
FROM titles)
title_id, pub_id, pubdate
FROM titles
ORDER BY pubdate DESC
go

title_id pub_id pubdate
-------- ------ -----------------------
CH9009 9903 2009-05-31 00:00:00.000
PC9999 1389 2009-03-31 00:00:00.000
FI0375 9901 2008-09-24 00:00:00.000
DR4250 9904 2008-09-21 00:00:00.000
BI4785 9914 2008-09-20 00:00:00.000
BI0194 9911 2008-09-19 00:00:00.000
BI3224 9905 2008-09-18 00:00:00.000
FI0435 9917 2008-09-17 00:00:00.000
FI0792 9907 2008-09-13 00:00:00.000

Note

Be aware that the TOP keyword does not speed up a query if the query also contains an ORDER BY clause. The reason is that the entire result set is selected into a worktable and sorted before the top N rows in the ordered result set are returned.


When using the TOP keyword, you can also add the WITH TIES option to specify that additional rows should be returned from the result set if duplicate values of the columns specified in the ORDER BY clause exist within the last values returned. The WITH TIES option can be specified only if an ORDER BY clause is specified. The following query returns the top four most expensive books:

SELECT TOP 4 price, title
FROM titles
ORDER BY price DESC
go

price title
--------------------- --------------------------------------
17.1675 But Is It User Friendly?
17.0884 Is Anger the Enemy?
15.9329 Emotional Security: A New Algorithm
15.894 You Can Combat Computer Stress!

If you use WITH TIES, you can see that there is an additional row with the same price (15.894) as the last row returned by the previous query:

SELECT TOP 4 WITH TIES price, title
FROM titles
ORDER BY price DESC
go

price title
--------------------- ---------------------------------------
17.1675 But Is It User Friendly?
17.0884 Is Anger the Enemy?
15.9329 Emotional Security: A New Algorithm
15.894 The Gourmet Microwave
15.894 You Can Combat Computer Stress!

In versions of SQL Server prior to 2005, if you wanted to limit the number of rows affected by an UPDATE statement or a DELETE statement, you had to use the SET ROWCOUNT statement:

set rowcount 100
DELETE sales where ord_date < (select dateadd(year, 1, min(ord_date)) from sales)
set rowcount 0



SET ROWCOUNT often was used in this way to allow backing up and pruning of the transaction log during a purge process and also to prevent lock escalation. The problem with SET ROWCOUNT is that it applies to the entire current user session. You have to remember to set the rowcount back to 0 to be sure you don’t limit the rows affected by subsequent statements. With TOP, you can more easily specify the desired number of rows for each individual statement:

DELETE top (100) sales
where ord_date < (select dateadd(year, 1, min(ord_date)) from sales)

UPDATE top (100) titles
set royalty = royalty * 1.25

You may be thinking that using TOP in INSERT statements is not really necessary because you can always specify it in a SELECT query, as shown in Listing 1.

Listing 1. Limiting Rows for Insert with TOP in a SELECT Statement
CREATE TABLE top_sales
(stor_id char(4),
ord_num varchar(20),
ord_date datetime NOT NULL,
qty smallint NOT NULL,
payterms varchar(12) ,
title_id dbo.tid NOT NULL)
go
insert top_sales
select top 100 * from sales
where qty > 1700
order by qty desc

However, you may find using the TOP clause in an INSERT statement useful when inserting the result of an EXEC command or the result of a UNION operation, as shown in Listing 2.

Listing 2. Using TOP in an Insert with a UNION ALL Query
insert top (50) into top_sales
select stor_id, ord_num, ord_date, qty, payterms, title_id from sales
where qty >= 1800
union all
select stor_id, ord_num, ord_date, qty, payterms, title_id from sales_big
where qty >= 1800
order by qty desc



When a TOP (n) clause is used with DELETE, UPDATE, or INSERT, the selection of rows on which the operation is performed is not guaranteed. If you want the TOP(n) clause to operate on rows in a meaningful chronological order, you must use TOP together with ORDER BY in a subselect statement. The following query deletes the 10 rows of the sales_big table that have the earliest order dates:

delete from sales_big
where sales_id in (select top 10 sales_id
from sales_big order by ord_date)

To ensure that only 10 rows are deleted, the column specified in the subselect statement (sales_id) must be the primary key of the table. Using a nonkey column in the subselect statement could result in the deletion of more than 10 rows if the specified column matched duplicate values.

Note

SQL Server Books Online states that when you use TOP (n) with INSERT, UPDATE, and DELETE operations, the rows affected should be a random selection of the TOP(n) rows from the underlying table. In practice, this behavior has not been observed. Using TOP (n) with INSERT, UPDATE, and DELETE appears to affect only the first n matching rows. However, because the row selection is not guaranteed, it is still recommended that you use TOP together with ORDER BY in a subselect to ensure the expected result.

Other  
  •  SQL Server 2008 : Transact-SQL Programming - The max Specifier
  •  SQL Server 2008 : T-SQL Tips and Tricks (part 3) - Generating T-SQL Statements with T-SQL & De-Duping Data with Ranking Functions
  •  SQL Server 2008 : T-SQL Tips and Tricks (part 2) - Using CONTEXT_INFO & Working with Outer Joins
  •  SQL Server 2008 : T-SQL Tips and Tricks (part 1) - Date Calculations & Sorting Results with the GROUPING Function
  •  SQL Server 2008 : General T-SQL Performance Recommendations
  •  SQL Server 2008 : General T-SQL Coding Recommendations (part 2) - Avoid SQL Injection Attacks When Using Dynamic SQL & Comment Your T-SQL Code
  •  SQL Server 2008 : General T-SQL Coding Recommendations (part 1) - Provide Explicit Column Lists & Qualify Object Names with a Schema Name
  •  SQL Server 2008 : Advanced Stored Procedure Programming and Optimization - Using Extended Stored Procedures
  •  SQL Server 2008 : Advanced Stored Procedure Programming and Optimization - Installing and Using .NET CLR Stored Procedures
  •  SQL Server 2008 : Advanced Stored Procedure Programming and Optimization - Using Dynamic SQL in Stored Procedures
  •  
    Video
    Top 10
    SG50 Ferrari F12berlinetta : Prancing Horse for Lion City's 50th
    The latest Audi TT : New angles for TT
    Era of million-dollar luxury cars
    Game Review : Hearthstone - Blackrock Mountain
    Game Review : Battlefield Hardline
    Google Chromecast
    Keyboards for Apple iPad Air 2 (part 3) - Logitech Ultrathin Keyboard Cover for iPad Air 2
    Keyboards for Apple iPad Air 2 (part 2) - Zagg Slim Book for iPad Air 2
    Keyboards for Apple iPad Air 2 (part 1) - Belkin Qode Ultimate Pro Keyboard Case for iPad Air 2
    Michael Kors Designs Stylish Tech Products for Women
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    Popular Tags
    Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone