从逻辑上讲,关系数据应该始终视为无序列表。主键的目的是唯一标识行,而不是排序表。SQL SERVER通常按主键(因为那可能是聚集索引)顺序返回数据。但对该顺序没有逻辑保证。使用ORDER BY子句是对结果集排序的唯一正确途径。
SQL可以对多列进行排序,且排序列不几是SELECT返回的列,这样如何指定列具有很强的灵活性。使用Management Studio中的查询设计器,选择列的排序顺序来创建ORDER BY,如下图:
一、通过使用列名称来指定顺序
排序结果的最佳方式是完整拼出ORDER BY列:
Use Database1
SELECT FirstName,LastName
From dbo.Customer
ORDER BY LastName,FirstName;
注意:ORDER BY 子句和选择列表中的列顺序是完全无关的。
二、使用表达式指定顺序
在用表达式进行排序的情况下,可以在ORDER BY子句中重复整个表达式。这不会影响性能,因为Sql Server 查询优化器叛党智能,能避免重复计算表达式:
SELECT FirstName+’, ’+LastName
From dbo.Customer
ORDER BY FirstName+’, ’+LastName;
三、使用列别名指定顺序
使用列别名来指定ORDER BY子句中使用的列。由于这种方法易于读取代码,因此它是按表达式排序的首选方法。请注意:该示例是按降序排序,而不是默认的升序:
SELECT FirstName+’, ’+LastName as FullName
From dbo.Customer
ORDER BY FullName DESC;
ORDER BY子句允许别名存在,但WHERE子句不允许,因为逻辑上处理列及表达式前先执行WHERE子句。ORDER BY子句在组合列和别名后执行,因此可以使用列别名。
四、使用列的顺序位置
列的序号(列位置编号)可用于表示ORDER BY列,但最好不要这样做。如果修改了选择列或它们的顺序,则排序也发生改变。如下:
SELECT FirstName+’, ’+LastName as FullName
From dbo.Customer
ORDER BY 1;
五、ORDER BY和排序规则
Sql Server的排序规则顺序对于数据排序非常重要,除了决定字母,排序规则顺序还决定排序顺序是否考虑重音、大小写以及其他字母属性。例如,如果排序规则区分大小写,则大写字母排在小写字母之前。下面的函数报告了的排序规则选项和当前的排序规则服务器属性。
SELECT * FROM fn_helpcollations();
读者可以试,会返回一个2397行的结果集。
下面的查询报告了当前服务器的排序规则:
SELECT SERVERPROPERTY('COLLATION') AS SERVERCOLLATION;
执行结果如下图:
虽然安装过程中就确定了服务器的排序规则设置,但使用COLLATE关键字可以设置数据库或下个星期的排序规则属性。下面的代码修改KHV11数据库的排序规则,使它区分大小写:
第一步:先把数据库设置为单用户模式:
EXEC sp_dboption 'KHV11', 'Single User', 'TRUE'
第二步:修改排序规则
ALTER DATABASE KHV11
COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS;
第三步:查询修改后的排序规则
SELECT DataBasePropertyEX('KHV11','COLLATION') AS DatabaseCOLLATION;
第四步:把数据库排序规则重新设置为原状
ALTER DATABASE KHV11
COLLATE Chinese_PRC_CI_AS;
第五步:把数据库设置为非单用户模式
EXEC sp_dboption 'KHV11', 'Single User', 'FALSE'
Sql Server不仅可以在服务器、数据库和列级别设置规则,甚至可以在单独的查询级别设置排序规则。下面的查询根据Danish排序规则进行排序,不考虑大小写或重音:
SELECT *
FROM dbo.Product
ORDER BY ProductName
Collate Danish_Norwegian_CI_AI
并不是所有的查询都需要排序,但对于那些确定需要排序的查询,ORDER BY子句结合许多可能的排序规则,在结果集的排序方面,表现了极大的灵活性。
注意:关于查询语句终止语句
ANSI SQL使用分号终止语句,虽然它已经是多个版本,但直到最近的一个选项Sql Server社区才听说了带分号的代码。Sql Server2005开始将它用于一些命令。因此,这里有许多关于分号的规则。
需要分号的情况:
●公用表达式(CTE)前的语句的结尾。
●MERGE语句的结尾。
不使用分号的情况:
●END TRY 和BEGIN CATCH了句之间。
●IF条件和BEGIN之间。
●切勿将GO和分号放在同一行。