云之飞踢 2020-02-19
我们知道在SQL语句中,ORDER BY语句可以用来排序。但是在SQL Server中,如果我们在子查询、视图、内联函数等数据库对象中单独使用ORDER BY语句是不允许的,来看下面的SQL语句:
SELECT * FROM ( SELECT [ID],[Code],[Name],[Age],[Sex],[Class] FROM [dbo].[Student] ORDER BY [ID] DESC ) AS T_Student
执行该语句,SQL Server会报错,错误信息如下:
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
该错误信息明确地指出ORDER BY语句不能够在子查询、视图、内联函数等数据库对象中使用,除非是用了TOP、OFFSET、FOR XML语句。
这个错误是微软想让开发者明白一个道理,那就是像子查询、视图、内联函数等这种中间结果查询,是不应该负责对查询结果进行排序的,对查询结果排序是最外层查询才应该做的事情,而不是中间结果查询该做的事。
那么为什么加了TOP、OFFSET、FOR XML语句后,子查询、视图、内联函数等数据库对象中就可以用ORDER BY语句了呢?那是因为这时ORDER BY语句只起到数据筛选的作用,并不是对查询结果排序。举个例子,如果我们要得到[Student]表中[ID]列最大的5条数据记录,就可以在子查询中将ORDER BY语句和TOP语句放在一起使用,如下所示:
SELECT * FROM ( SELECT TOP 5 [ID],[Code],[Name],[Age],[Sex],[Class] FROM [dbo].[Student] ORDER BY [ID] DESC ) AS T_Student
这个SQL语句是不会报错的,执行结果如下:
所以我们可以看到[ID]列最大的5条数据记录,就被查询出来了。但是我们前面说了ORDER BY语句在子查询、视图、内联函数等数据库对象中只起到数据筛选的作用,所以如果我们真的想对[ID]列排序,应该在最外层查询再使用ORDER BY语句(虽然上面截图的查询结果中,数据已经按照[ID]列的降序排列,但事实上SQL Server并不保证每次查询结果肯定是按照[ID]列降序排列,你可以认为这只是一个巧合),如下所示:
SELECT * FROM ( SELECT TOP 5 [ID],[Code],[Name],[Age],[Sex],[Class] FROM [dbo].[Student] ORDER BY [ID] DESC ) AS T_Student ORDER BY [ID] DESC
所以真正起到对查询结果进行排序的是最外层查询的ORDER BY语句,而不是子查询中的ORDER BY语句。