SQL Server 2012 大幅增強了T-SQL

fmms 12年前發布 | 20K 次閱讀 SQL Server

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_resultsys.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 輸入為空字符來完成同樣的工作,不過這樣做代碼會讓代碼顯得混亂。

 本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!