SQL Server 2012中新的T-SQL命令第一部分

日期: 2012-07-09 作者:Serdar Yegulalp翻译:冯昀晖 来源:TechTarget中国 英文

编者按:本系列文章介绍了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”命令……

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

编者按:本系列文章介绍了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 ”也有一个非常好的分析说明,对于每种命令适合使用的场景都举了详细的例子。

作者

Serdar Yegulalp
Serdar Yegulalp

Serdar Yegulalp从1994年到2001年为Windows杂志写作,覆盖了广泛的技术方面。他现在是《The Windows 2000 Power Users Newsletter》一书的出版者,辛勤钻研他擅长的Windows NT, Windows 2000 and Windows XP领域,并为TechTarget写专栏。

相关推荐