Thursday, November 21, 2024
HomeProductsSQL Server ToolsUsing Alternatives for the LIMIT Clause in SQL Server

Using Alternatives for the LIMIT Clause in SQL Server

In database management, efficient limiting of query results is crucial for optimizing performance and ensuring the retrieval of relevant data. Many SQL database systems, such as MySQL and PostgreSQL, utilize the LIMIT clause to specify the number of records a query returns. However, SQL Server doesn’t support the LIMIT clause, opting instead for alternatives like TOP, OFFSET-FETCH, and SET ROWCOUNT. This design choice reflects SQL Server’s focus on flexibility and performance, offering various methods to achieve similar functionality while catering to different use cases and scenarios.

Let’s take a closer look at the LIMIT alternatives in SQL Server, highlighting their unique features and limitations.

Contents

Using the SELECT TOP clause

In SQL Server, the SELECT TOP clause acts as an alternative to the LIMIT clause. Likewise, it’s used to limit the number of rows returned by a query. It’s especially useful when you’re dealing with large datasets and want to retrieve only a subset of records. The basic syntax is:

SELECT TOP (number | percent) column_names
FROM table_name;

Here, number stands for the exact number of rows to return, and percent is the percentage of rows to return from the total result set. Use one of these arguments depending on your needs.

You can refine the results further by adding other clauses—like WHERE or ORDER BY. If you’d like to know more about clauses used with SELECT, check out the post about the SQL SELECT statement.

For example, the following query returns the first five employees ordered by the date they were hired (here and below, we’ll be using the AdventureWorks2022 sample database in our examples):

USE AdventureWorks2022;

SELECT TOP 5 *
FROM HumanResources.Employee
ORDER BY HireDate;

Or, this query retrieves national IDs and job titles of the top 10% of employees who have more than 20 hours of vacation:

USE AdventureWorks2022;

SELECT TOP 10 PERCENT NationalIDNumber, JobTitle
FROM HumanResources.Employee
WHERE VacationHours > 20;

Using the SELECT TOP clause brings a number of advantages. First, performance optimization—it limits the size of the result set, reducing memory and processing load when only a portion of the data is needed. Next, it can be used to create efficient pagination for large result sets by retrieving only the rows required for the current page. Also, it’s helpful when testing queries on large tables by limiting the number of returned rows.

Note that SELECT TOP doesn’t provide random rows. To achieve randomness, you can combine it with ORDER BY NEWID(), but this can be inefficient for large datasets. On the other hand, without specifying an ORDER BY clause, the results can be unpredictable since SQL Server doesn’t guarantee the order of returned rows.

Implementing pagination with OFFSET-FETCH

Speaking of pagination, another clause—OFFSET-FETCH—can be used in SQL Server to implement pagination, allowing you to retrieve a specific subset of records by skipping a number of rows and then fetching a defined number of rows. This clause has the following syntax:

SELECT column_names
FROM table_name
ORDER BY column_name
OFFSET number_of_rows_to_skip ROWS
FETCH NEXT number_of_rows_to_return ROWS ONLY;

The OFFSET clause lets you specify how many rows need to be skipped before returning rows, and FETCH NEXT defines how many rows to return after the skipped ones.

To illustrate, imagine you need to skip the first ten records sorted by BusinessEntityID and return the next ten, effectively fetching page 2 in a paginated result. Your query will look like this:

USE AdventureWorks2022;

SELECT *
FROM HumanResources.Employee
ORDER BY BusinessEntityID
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;

You can also use OFFSET-FETCH with a dynamic page size and page number. For example, this dynamic query fetches records for page 3, assuming a page size of ten rows per page:

USE AdventureWorks2022;

DECLARE @PageSize INT = 10;
DECLARE @PageNumber INT = 3;

SELECT BusinessEntityID, JobTitle, HireDate
FROM HumanResources.Employee
ORDER BY BusinessEntityID
OFFSET (@PageSize * (@PageNumber - 1)) ROWS
FETCH NEXT @PageSize ROWS ONLY;

This combination of clauses is great because it gives you precise control over paging—you get a clean and efficient way to handle pagination, especially for web applications. Moreover, OFFSET-FETCH adheres to the SQL standard, making it portable and easy to understand for developers coming from other RDBMS. On top of that, unlike other methods (such as using ROW_NUMBER() with subqueries), OFFSET-FETCH directly skips and fetches rows without the need for complex workarounds.

It’s worth noting, though, that—for large datasets—the further you go in the pagination (say, page 1000), the slower the query might become because SQL Server has to skip more rows. Another point to consider is that OFFSET-FETCH doesn’t return the total number of rows, so if you need to display pagination metadata (like the total number of pages), an additional query—COUNT(*)—is required to fetch the total row count. And don’t forget that an ORDER BY clause is mandatory when using OFFSET-FETCH; otherwise, the results are unpredictable.

Using the SET ROWCOUNT command

You can use the SET ROWCOUNT command in SQL Server to limit the number of rows returned by a SELECT statement or affected by UPDATE or DELETE. The command’s syntax is as follows:

SET ROWCOUNT { number | 0 }

Instead of number you specify the number of rows to return or process, and 0 resets the row count.

If you use SET ROWCOUNT and SELECT together with other commands such as ORDER BY and WHERE, their interaction can be quite powerful. In this combination, the WHERE clause filters the rows first, the ORDER BY clause sorts the filtered rows, and then SET ROWCOUNT limits the number of rows returned from the sorted result set.

Here’s an example where we want to retrieve only the top five records of alphabetically sorted (by their job title) employees with over 50 hours of vacation and then reset the row count limit so that future queries return all matching rows:

USE AdventureWorks2022;

SET ROWCOUNT 5;
SELECT *
FROM HumanResources.Employee
WHERE VacationHours > 50
ORDER BY JobTitle;
SET ROWCOUNT 0;

SET ROWCOUNT with data modification commands such as UPDATE or DELETE works similarly. Let’s consider an example of updating data. Running this script will change the job title to Chief Stocker for only the first of the employees with the Stocker job title, then reset the row count limit, and display the result:

USE AdventureWorks2022;

SET ROWCOUNT 1;
UPDATE HumanResources.Employee
SET JobTitle = 'Chief Stocker'
WHERE JobTitle = 'Stocker';
SET ROWCOUNT 0;

-- To see the result of the update
SELECT *
FROM HumanResources.Employee
WHERE JobTitle LIKE ('%Stocker%')
ORDER BY JobTitle;

As you can see, SET ROWCOUNT provides a simple method for limiting results without complex syntax. Unlike TOP, which sometimes requires subqueries for more complex logic, SET ROWCOUNT can be used directly with a SELECT statement. However, the SET ROWCOUNT command is considered deprecated for limiting result sets in favor of the TOP clause, which offers clearer semantics.

As a downside, the effect of SET ROWCOUNT is session-specific, meaning it must be set in each session where it’s needed. In addition, using SET ROWCOUNT in more complex queries can lead to unintended results if not carefully applied.

Note that SET ROWCOUNT is less and less commonly used today. SQL standards have evolved, and modern SQL practices favor more explicit control over result sets and data manipulation. So Microsoft recommends using the TOP clause instead, as SET ROWCOUNT won’t affect DELETE and UPDATE statements in future releases following the SQL Server 2022 version.

Try it yourself with dbForge Studio

We’ll try one of the above use cases in dbForge Studio for SQL Server.

Let’s first check how many employees in the HumanResources.Employee table of the AdventureWorks2022 database are holding the Marketing Specialist position. We do this as follows:

SELECT
  COUNT(*) AS Count
FROM HumanResources.Employee
WHERE JobTitle = 'Marketing Specialist';

As we can see, there are five of them:

We want to know three specialists who have the largest number of unused vacation hours. We use the following query:

SET ROWCOUNT 3;
SELECT
  *
FROM HumanResources.Employee
WHERE JobTitle = 'Marketing Specialist'
ORDER BY VacationHours DESC;
SET ROWCOUNT 0;

And dbForge Studio returns the result (we’ve changed the order of columns just for the purpose of this demonstration):

Why dbForge Studio for SQL Server? We believe that dbForge Studio—with its enhanced user interface and advanced features—outshines SQL Server Management Studio (SSMS). While SSMS revolves around the basics, dbForge Studio offers sophisticated tools like visual query building, database comparison and synchronization, data aggregation and analysis, automated unit testing, and integration with version control systems. This focus on user experience and powerful capabilities makes dbForge Studio a compelling alternative to SSMS for SQL Server management. To know more, watch this video: SSMS vs dbForge Studio for SQL Server – Features Comparison.

Got interested? You can try out dbForge Studio for SQL Server by downloading it for a free 30-day trial. The installation guide will help you get dbForge Studio running.

Comparing the alternatives

To sum up, let’s briefly compare the SQL Server alternatives to the LIMIT clause we’ve discussed above:

  1. SELECT TOP: Best for quick retrieval of a specified number of rows from a result set, especially when you need a fixed limit. Ideal for reports or dashboards where only the top N records are required.
  2. OFFSET-FETCH: Most appropriate for pagination in larger datasets. It allows you to skip a specified number of rows and return a defined set, making it great for displaying results across multiple pages.
  3. SET ROWCOUNT: Useful for limiting rows in older versions of SQL Server or for updating or deleting a specific number of records. However, its use is declining in favor of TOP and OFFSET-FETCH.

So, each method has its unique strengths depending on the use case.

Further learning

We’d like to offer you the following resources to learn more about dbForge Studio for SQL Server, what it can do, and how to use it:

RELATED ARTICLES

Whitepaper

Social

Topics

Products