天天看點

SQL Server 2012大幅增強了T-SQL

SQL Server 2012對T-SQL進行了大幅增強,其中包括支援ANSI FIRST_VALUE和LAST_VALUE函數,支援使用FETCH與OFFSET進行聲明式資料分頁,以及支援.NET中的解析與格式化函數。

  Fetch與Offset

  目前,對于實作服務端分頁,SQL Server開發人員傾向于選擇使用指令式技術,如将結果集加載入臨時表,對行進行編号,然後從中挑選感興趣的範圍。有一些開發人員選擇使用更加時髦的ROW_NUMBER和OVER模式。另外,還有一些開發人員堅持使用遊标。雖然這些技術都不是太難,但是它們可能會較為耗時并且容易出錯。不僅如此,由于每個開發人員都有自己中意的實作方式,進而造成這些技術并不一緻。

  SQL Server 2012通過增加聲明式資料分頁解決了該問題。開發人員可以通過在T-SQL的ORDER BY子句後加上OFFSET和FETCH NEXT選項來完成資料分頁。目前SQL Server并沒有為其做性能優化,而隻是幫助完成使用者需要手工完成的工作。正如Greg Low博士在示範中所說,隻有當使用者知道你試圖解決的問題是什麼,而不是知道你怎樣去解決問題的時候,他們才可以更好地編寫出查詢優化來對性能進行改善。

  Over子句視窗

  有時候開發人員需要基于行之間的差異來編寫查詢。例如,你可能有興趣想知道處理目前行與上一行之間所花去的時間。使用遊标很容易解決該問題,但由于其風格和性能原因,大家并不怎麼使用。你還可以使用子查詢進行逐行執行,但這樣的代價實在太過昂貴。最後,你還可以将問題推給用戶端,但這需要用戶端是一門程式設計語言而不隻是一個報表工具方能起效。

  現在你可以使用LAG函數直接通路上一行。由于使用者顯式聲明了試圖完成的工作,是以查詢分析器會在記憶體中保留上一行,而不再需要建立一個子查詢,這反過來也極大地提升了性能。雖然LAG預設為上一行,但是如果你需要進一步回溯,可以在其中指定偏移量。

  LAG與它的姊妹函數LEAD均為ANSI标準的一部分。該特性自從微軟在SQL Server 2005中部分實作OVER子句時,就一直被開發人員要求加入。

  這一版本還支援了FIRST_VALUE和LAST_VALUE。

  反射

  先前開發人員若想要确定查詢或存儲過程的傳回結果類型,需要使用SET FMTONLY指令。使用該指令可以在不需要實際執行查詢的情況下預覽傳回結果的列資訊。可惜的是,傳回的資訊僅僅局限于列的定義,而如果隻要先前執行查詢便能夠獲得這些資訊。

  通過使用新的sp_describe_first_result_set存儲過程,開發人員可以獲得查詢和存儲過程傳回結果的詳細資訊。這些資訊包括資料類型及其規模、源表/列,列是否可被更新或由計算而得,以及其他大量資訊。動态管理視圖sys.dm_exec_describe_first_result和sys.dm_exec_describe_first_result_set_for_object同樣具有該特性。

  防禦式程式設計(Defensive Coding)

  開發人員在調用同僚編寫的存儲過程時通常很頭疼,這是因為存儲過程傳回結果在編譯期沒有保證,是以意外的破壞性改動成了一大顧慮。盡管T-SQL沒有提供任何手段來預防這些錯誤,但是可以借助RESULT SETS選項将錯誤發生率降至最低。

  開發人員可以通過指定RESULT SETS選項要求存儲過程傳回特定的資料結構。如果存儲過程傳回的結果集與被要求的有出入,将會發生錯誤并導緻批次中止。由于發生的錯誤是運作時錯誤,是以我們建議使用該選項的開發人員建立完整系列的單元測試,以確定代碼在接觸生成環境前可以觸發該錯誤。

  錯誤處理

  T-SQL從2005年就開始支援TRY-CATCH ,但奇怪的是,直到現在才有了THROW。THROW不帶參數,它的用法與C#和VB中catch塊中的throw類似。也就是說,它會重新抛出異常,而不會丢失當時捕捉到的任何資訊。它對于向重試隊列記錄或添加條目很有幫助,同時也可以通知應用程式出錯。

  當THROW帶參使用時,它類似于RAISERROR,不同之處在于它支援sys.messages之外的錯誤資訊号(error number),并且它的嚴重級别(severity)總是16。還有一點與RAISEERROR不同的是,所有未被捕獲的THROW錯誤總是批量終止。

  解析和轉換

  T-SQL目前支援PARSE函數,該函數包含選項用于指定區域性設定(Culture)。區域性設定是.NET架構支援的諸多特性之一,用于表明解析如何實作,TRY_PARSE函數也包含該選項。

  類似的,還有一個新的TRY_CONVERT函數。這兩者以及try parse函數在轉換失敗後會傳回null。

  另一方面,FORMAT函數采用了.NET格式化設定。盡管與本地函數(如STR)相比它的速度稍慢,但是卻更加靈活。

  日期/時間函數

  雖然T-SQL仍然遠沒達到完美,但至少日期/事件函數處理上有了些許改善。EOMONTH函數用于傳回月份的最後一天,這對報表是一個非常有用的特性。xxxFROMPARTS系列函數使用一系列參數而不是單個字元串來構造日期和時間。它包含了對資料類型Date、DateTime、DateTime2、DateTimeOffset、SmallDate以及Time的支援。

  混合函數(Misc. Function)

  T-SQL包含了Access和Visual Basic中Choose的函數。在某些情況下,它可以被當成一個簡化版的CASE使用。另外一個從這些語言中借鑒的函數是IIF。

  CONCAT可用于字元串拼接。它除了可以讓代碼更容易地移植到其他資料庫語言中,還提供了與+運算符不一樣的null處理方式。Itzik Ben-Gan寫道:

  > 連接配接運算符+在輸入為NULL時會産生結果NULL。而CONCAT函數在轉換前将NULL輸入轉換為空字元串。 當然,你可以使用COLAESCE函數替換NULL輸入為空字元來完成同樣的工作,不過這樣做代碼會讓代碼顯得混亂。

本文轉自 wws5201985 51CTO部落格,原文連結:http://blog.51cto.com/wws5201985/817452,如需轉載請自行聯系原作者