SQL Server 2012中新的T-SQL命令第一部分
SQL Server 2012中新的T-SQL命令第一部分
SQL Server的每个版本在Transact-SQL(T-SQL)方面都会有些新的变化,这些变化会让程序员的工作变得更加轻松,同时也会实现SQL Server用户社区提出的一些需求。当然SQL Server 2012也是如此。在本文中,我将介绍几个用户需要注意的新的T-SQL命令。
WITH RESULT SETS (在 EXECUTE命令中)
“WITH RESULT SETS”命令解决了困扰大多数人的问题,编写存储过程作为他们业务逻辑一部分的用户都遇到过这个问题:列名往往是不能改变的。
假定你创建了一个存储过程,返回几列数据,都有指定的名称和数据类型。虽然你每次运行存储过程时,你都只能获得那些名称和数据类型的结果。但如果你修改存储过程,修改输出,就有可能出现与其它组件不兼容的情况(包括SQL Server内部的和外部的组件)。
我们有很多种方法可以解决这个问题:例如,创建并行存储过程,返回新格式的结果,然后逐步把所有逻辑迁移到新存储过程中来。然而在迁移期间,一般需要维护两套存储过程,不管这个过程持续多久。
“WITH RESULT SETS”的出现解决了这一问题,而且在我看来是更优雅的一种处理方式。它可以支持你在调用存储过程时,通过使用指令重新定义存储过程的结果集名称和类型,请看下面示例:
EXEC myStoredProcedure 123
上面命令正常会返回“int”类型列,名称是“Result_Code”。由于业务逻辑的变化,我们需要让列名称改为“ResultCode”。(可以采取的做法是:实行一个标准,规定列如何命名,且不允许出现下划线)。我们不需要修改存储过程本身,我们只需要修改存储过程的调用之处,请看下面命令:
EXEC myStoredProcedure 123
WITH RESULT SETS
([ResultCode] int NOT NULL)
还有一个方法,你可以使用“WITH RESULT SETS”返回多个结果集:
EXEC myStoredProcedure 123
WITH RESULT SETS
([ResultCode] int NOT NULL),([Result_Code] int NOT NULL)
这个命令会给客户端返回两个结果集第一个结果集是“新格式”的,第二个结果集是“原来的格式”。这样你可以让客户端选择哪一个结果集更适合使用,这都是同一个命令返回来的。
“OFFSET ”和“FETCH ”(在“ORDER BY”从句中使用)
大部分SQL Server DBA发现他们自己都需要以分页形式提供结果。对于这个问题,有许多类似“半成品”的解决方案,从简单地把应用程序整个结果集本地缓存然后在本地做分页计算,到使用“NOT IN”或者其它非常消耗性能的命令等。
新的“OFFSET ”命令带来了一种优雅的方法,在查询端做整体分页。我们来看看命令怎么写:
SELECT [UserID], [UserName]
FROM [UserTable]
ORDER BY [Username] ASC
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY
结果基本正是你所期望的:SQL Server从表中读取数据,跳过了查询返回的前十行,然后只返回接下来的十行数据。这比使用嵌套查询加上“TOP x”类型限制少了很多不便。
要注意,当你使用“OFFSET/FETCH”提取结果时,结果会当成是一个独立的事务,而不是像游标那样的对象。比方说下面这种情况:
1.你使用类似上面这样的命令取到了表中的前十行。
2.当你处理这些行时,该表接受了其它插入语句,增加的行会出现在你查询的第一页中。
3.你该取接下来的十行,但是你取到的接下来十行将包括新增到该表中的数据,而不是基于第一次查询得到的结果集中的下一个十行数据。
在编写应用程序时要留意,确保你的数据分页方式定义的条件不会违背常理(或者,更糟糕的情况下,你可能会无意中创建引起数据完整性问题的条件)。
THROW
SQL Server中的错误处理通常是通过“RAISERROR ”命令实现的。然而,“RAISERREOR ”有几个限制:它只能返回“ sys.messages”中定义的错误码,尽管你可以使用大于50000的错误码来创建自定义错误类型。(默认是50000,但是你可以指定其它编码)。也就是说,这对于处理系统级错误是最有用的,但是对于具体涉及你数据库的错误就不是很合适了。新命令“THROW ”支持错误捕获操作,这样可以更好地适合T-SQL用户的应用。我们把它与“RAISERROR ”命令的方式进行比较,就可以看到它们彼此特点如何,哪种最适合你的情况。
1.最重要的一点:“RAISERROR ”总是产生新的异常,不管什么时候调用。所以在例程执行期间任何之前生成的异常(例如,一些CATCH块之外的异常)都会抛弃。“THROW ”可以重新抛出原异常,触发“CATCH”代码块,所以它可以提供该错误的更多上下文信息。
2.“RAISERROR ”用来产生应用级的和系统级的错误代码。“THROW ”只产生应用级的错误(错误码大于等于50000的那部分)
3.如果你使用错误码“50000”或者更大的错误码编号,“RAISERROR ”只能传递自定义错误消息;而“THROW ”支持传入任何想要的错误文本。
4.“RAISERROR ”支持标记替代;“THROW ”不支持。
5.“RAISERROR ”支持任何安全级别的错误;“THROW ”只支持安全级别16的错误。
总而言之,设计“THROW ”命令主要是给T-SQL脚本和存储过程在你需要返回自定义错误时用的,这些错误是为你创建的应用程序专门自定义的。微软MVP Leonard Lobel在他的博客中对于“THROW ”和“RAISERROR ”也有一个非常好的分析说明,对于每种命令适合使用的场景都举了详细的例子。
本文转载自企业级IT信息服务平台-网界网-CNW.com.cn
免责声明:本文仅代表作者个人观点,与世界朋友网无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。