SQL SERVER – ORDER BY Does Not Work – Limitation of the Views Part 1

Update: Please read the summary post of all the 11 Limitations of the view SQL SERVER – The Limitations of the Views – Eleven and more…

Recently, I was about the limitations of views. I started to make a list and realized that there are many limitations of the views. Let us start with the first well-known limitation.

Order By clause does not work in View. I agree with all of you  who say that there is no need of using ORDER BY in the View. ORDER BY should be used outside the View and not in the View. This example is another reason why one should not use ORDER BY in Views.

Here is the quick example for the same. I have used sample database AdventureWorks for the example.

USE AdventureWorks
GO
-- First Run regular query and observe
SELECT *
FROM Sales.SalesOrderDetail
ORDER BY SalesOrderDetailID DESC
GO
-- Create view with same T-SQL Script
IF EXISTS (SELECT * FROM sys.views WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[vw_ViewLimit1]'))
DROP VIEW [dbo].[vw_ViewLimit1] GO
CREATE VIEW vw_ViewLimit1
AS
SELECT
*
FROM Sales.SalesOrderDetail
ORDER BY SalesOrderDetailID DESC
GO
/*
Above Query will throw following error
Msg 1033, Level 15, State 1, Procedure vw_ViewLimit1, Line 5
The ORDER BY clause is invalid in views, inline functions,
derived tables, subqueries, and common table expressions,
unless TOP or FOR XML is also specified.
*/
-- Create view with same T-SQL Script without ORDER BY
IF EXISTS (SELECT * FROM sys.views WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[vw_ViewLimit1]'))
DROP VIEW [dbo].[vw_ViewLimit1] GO
CREATE VIEW vw_ViewLimit1
AS
SELECT
*
FROM Sales.SalesOrderDetail
GO
-- Use Order by clause outside of the views
-- Create view with same T-SQL Script without ORDER BY
SELECT *
FROM vw_ViewLimit1
ORDER BY SalesOrderDetailID DESC
GO

If you try to include ORDER BY in View, it will throw the following error

Msg 1033, Level 15, State 1, Procedure vw_ViewLimit1, Line 5
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.

The above error itself explains how one can use ORDER BY in view. It suggests that if we use ORDER BY with TOP, we can surely use ORDER BY. If we want all the rows of the table, we can use TOP with 100 PERCENT. Let us try to modify our view with the usage of TOP 100 PERCENT and ORDER BY. This does not throw any error.

-- Create view with TOP 100 PERECENT and ORDER BY
IF EXISTS (SELECT * FROM sys.views WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[vw_ViewLimit1]'))
DROP VIEW [dbo].[vw_ViewLimit1] GO
CREATE VIEW vw_ViewLimit1
AS
SELECT TOP
100 PERCENT *
FROM Sales.SalesOrderDetail
ORDER BY SalesOrderDetailID DESC
GO
-- Select from view
SELECT *
FROM vw_ViewLimit1
GO

However, when you observe the resultset, you will notice that table is not ordered DESC, which is specified by SalesOrderDetailID column, as it should be. Let us examine the execution plan. You will not notice that there is no SORT operation at all.

SQL SERVER – ORDER BY Does Not Work – Limitation of the Views Part 1 ViewLimit1

SQL SERVER – ORDER BY Does Not Work – Limitation of the Views Part 1 ViewLimit2

I have heard many people talking about workaround, where they use some other number less than 100 in the TOP clause. Let us do a small test with 99.99 PERCENT and see the type of result we get.

-- Create view with TOP 99.99  PERECENT and ORDER BY
IF EXISTS (SELECT * FROM sys.views WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[vw_ViewLimit1]'))
DROP VIEW [dbo].[vw_ViewLimit1] GO
CREATE VIEW vw_ViewLimit1
AS
SELECT TOP
99.99 PERCENT *
FROM Sales.SalesOrderDetail
ORDER BY SalesOrderDetailID DESC
GO
-- Select from view
SELECT *
FROM vw_ViewLimit1
GO

Now let us check the result.We can clearly see that the result is Ordered by Column specified in the view.

SQL SERVER – ORDER BY Does Not Work – Limitation of the Views Part 1 ViewLimit3

However, as we are using TOP and 99.99, there is very little chance that we may not get all the rows from the table. Let us check the count of the rows in original table and Views.

-- Match the counts
SELECT COUNT(*) ViewCount
FROM vw_ViewLimit1
GO
SELECT COUNT(*) OriginalCount
FROM Sales.SalesOrderDetail
GO

From the count, it is clear that View has not returned all the rows because of the TOP specified. If table was a small table with less than 10,000 rows, this view might have not missed any rows, but in this case, where there are lots of rows, the View has missed rows.

SQL SERVER – ORDER BY Does Not Work – Limitation of the Views Part 1 ViewLimit4

Summary: It is not advisable to use ORDER BY in Views. Use ORDER BY outside the views. In fact, the correct design will imply the same. If you use TOP along with Views, there is a good chance that View will not return all the rows of the table or will ignore ORDER BY completely.

Please share your experience over here as comments.

Reference: Pinal Dave (https://blog.sqlauthority.com)

SQL Scripts, SQL View
Previous Post
SQL SERVER – Computed Columns – Index and Performance
Next Post
SQLAuthority News – Feedback Received for Virtual Tech Days Sessions on Spatial Database

Related Posts

64 Comments. Leave new

  • good post as usual pinal!

    Reply
  • Hi,

    this is an excellent article

    Reply
  • Hi Boss,

    Very nice explanation. Can you let us know why it is not working with “TOP 100” ?

    Tejas

    Reply
  • Marko Parkkola
    August 23, 2010 1:36 pm

    Funny thing.

    Create a view which you order by column A. Execute query where you order the view by column B. You get two sort operator to the execution plan.

    Reply
  • Sort order is not even guaranteed when using top 99,99.

    Reply
  • Jeremiah Peschka
    August 23, 2010 4:40 pm

    You left out the reason why ORDER BY isn’t allowed in a view, subquery, CTE, etc.

    The real reason why you can’t ORDER any of these things is because they are all sets. A set is an unordered collection of tuples. The reason that using ORDER BY with TOP works at all is because the use of TOP forces SQL Server to perform a cursor operation over the result set. Once you have a cursor, you can have an explicit order.

    Ben-Gan discusses this in T-SQL Querying and I suspect it’s buried somewhere in BOL as well.

    As an aside, the SELECT TOP x trick is scheduled to be deprecated in a future version of SQL Server, so it would be best to not to use it at all.

    Reply
  • Nice article pinal, also thanks for the explanation Jeremiah.

    Reply
  • Hey Pinal,
    Can you explain about Table spool/eager spool
    What is Table spool
    When the optimizer chooses table spool
    Its advantages and Disadvantages on performance

    Your examples will be easy to understand .
    Please provide info abt that

    thanks
    SANTOSH

    Reply
  • Hi Pinal,

    SQL Server honors the order by clause when we give it the number of rows to return

    for e.g. we can use a huge number in the top clause

    SELECT TOP 99999999999999
    Column1,
    Column2
    FROM
    dbo.Table
    Order by
    Column1

    Reply
    • Thanks Harsu! I usually don’t have a problem with an unsorted view, but the need just came up. I had to laugh when I saw it sorted when I ran it in design mode, but not the saved view. I don’t know what that’s all about.

      Reply
  • This post is the answer for a question that I received today. Thanks.

    Reply
  • Nakul Vachhrajani
    August 24, 2010 7:41 pm

    Let me start out by thanking you for yet another good, useful and very practical article.
    I have heard about the TOP 100 PERCENT * workaround (and have also seen a couple of test views compile successfully), but always had the question that Tejas had – why does that not work as expected?
    Jeremiah’s reasoning does clear things out a bit, however, currently, it looks like SQL is simply ignoring the ORDER BY clause when it encounters the TOP x clause – and with that being the case, it should be deprecated.

    Reply
  • good explain!!! i read daily your article you are a smart sql writer…

    Reply
  • Thanks Pinal for this post. When we use View in FROM clause, the result is not guaranteed to be in ORDER as view is a SET, as per ANSI standard. TSQL follows that.

    The ORDER BY clause in query is just for aiding TOP clause as TOP clause does not have its own ORDER BY clause and depends on the ORDER BY clause of the whole query. It will be helpful in SELECT query. But, of no use in a view.

    Reply
  • Nicely put sir. Thanks Jeremiah for some more inputs.

    Thanks,
    Suresh

    Reply
  • Good and useful post.

    My understaning of the use of ORDER BY in views was only to make the TOP clause work and that SQL Server makes no garantee to the actual order of the result in the view. It only garentees that the correct records are in the TOP clause.

    I have only found this to actually work with a TOP [number], but not with a TOP PERCENT. I never knew exactly why, but the discussion from this post gave me a little more clarity.

    Thank you, Everyone!

    Reply
  • To rely on the ORDER BY clause in a view definition is a same kind of mistake like to rely on the physical order of records inserted into an empty table.

    Even when it could sound unbelievable (because many commands you’ve executed in the past were ordered as you supposed) SQL SELECT simply ignores the physical order of records in table/view and the only clause which can ensure proper records order on output is the ORDER BY in your SELECT statement.

    Reply
  • nice article .. thanks for the explanation Jeremiah Peschka

    Reply
  • Just out of curiosity, I tried the following code:

    — Create view with TOP 99.9999 PERCENT and ORDER BY
    IF EXISTS (SELECT * FROM sys.views WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[vw_ViewLimit1]’))
    DROP VIEW [dbo].[vw_ViewLimit1]
    GO
    CREATE VIEW vw_ViewLimit1
    AS
    SELECT TOP 99.9999 PERCENT *
    FROM Sales.SalesOrderDetail
    ORDER BY SalesOrderDetailID DESC
    GO
    — Select from view
    SELECT *
    FROM vw_ViewLimit1
    GO

    You get all 121,317 rows from the table returned and the order is descending. It worked!!! This appears to be a precision issue in the expression of the TOP (expression) [PERCENT] clause. If you expand the scale out far enough, all rows in the table can be returned. I’m not recommending this technique, but I found it interesting that it could be made to work.

    Reply
  • Views are unordered sets (or bags depending on your specific definitions). They should be used as unordered sets.

    Yes, you can order them using the TOP workaround.

    But if you are using a View as something it isn’t intended to be, it makes me wonder what other design flaws are built into the system you are building or maintaining.

    My primary question to you would be: WHY are you attempting to order data within a View?

    The usual answer is: to support reporting. If this is the case, there are two options:

    Order the data within a stored procedure and bind your report to the stored procedure.

    -or-

    Order the data within the report.

    Ordering large sets of data within SQL Server forces the data to be stored and sorted within tempdb… a huge performance bottleneck, especially on a large, multiuser system

    Using a stored procedure means you are using the features of the application (SQL Server) as they are intended to be used and is supported by Microsoft.

    Using a view, then sorting the results in the client application means you are using the strengths of each of the components within your system effectively and efficiently.

    Just because you can do something (with a workaround) doesn’t mean you should do something.

    The most successful systems are those that use the strengths of the components that make up that system. Using the components in a sub-optimal way will result in a sub-optimal system

    Reply
  • I don’t get it. Why is ORDER BY without TOP a limitation? Because you get an error? Or because the performance is bad (according to you)? If you’re selecting ALL (or almost all with 99.99%) of the records from a table, how can you expect good performance? You’re forcing the QP to read all the pages of the clustered index. Of course the perrformance will be poor, but it’s a view. It means that some other code will want to use it as a “table”, by trying to SELECT (and maybe INSERT/UPDATE/DELETE if the definition of it allows to). Views are used with WHERE/GROUP BY/HAVING and other clauses, let alone participate in JOINs of all flavors. How can you assign an attribute of “bad” to an object by examining it the way you did? I always used in the past an “ordered” view only when building a BCP…OUT process, until SSIS came along. Now, if I do need to use BCP, I use QUERYOUT clause, where my options are unlimited.

    Reply

Leave a Reply