1. 程式人生 > >SQL Server 2012 T-SQL 新特性

SQL Server 2012 T-SQL 新特性

集成 decimal error 別名 ransac anti exception 序列 嘗試

原文:SQL Server 2012 T-SQL 新特性

序列 Sequence

SQL Server 現在將序列當成一個對象來實現,創建一個序列的例子語法如下:

CREATE SEQUENCE DemoSequence
START WITH 1
INCREMENT BY 1;

使用序列的方法如下所表達的:

SELECT VALUE FOR DemoSequence

序列與以前的種子列(identity)的區別很明顯,種子列只限於當前列,而序列是一個對象層面的實現,則可以在多個表之間共享。這一點特點在管理軟件序列號生成方面,是個不錯的開始。和種子列相似,序列也可以重置,例子如下

ALTER
SEQUENCE Samples.IDLabel RESTART WITH 1 ;

序列的值可以使用整型類型,比如tinyint, smallint, int, bigint, decimal 或是小數精度為0的數值類型。

序列的限制(limitation)有二個,一是序列不支持事務,即使事務中進行了回滾(rollback)操作,序列仍然返回下一個元素。

第二,序列不支持SQL Server 復制(replication),序列不會復制到訂閱的SQL Server實例中。如果一個表的默認值依賴一個序列,而序列又是不可復制的,這會導致訂閱的SQL Server出現腳本錯誤。

數據分頁 Page Data

SQL Server一直在改善數據分頁方法,SQL Server 2005內置的row_number函數可以實現,例子代碼如下

SELECT *
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY CustomerID) AS sequencenumber, *
FROM Customers) AS TempTable
WHERE sequencenumber > 10 and sequencenumber <= 20

SQL Server 2012有更簡潔的語法,例子代碼如下所示

SELECT *
FROM Customers
ORDER
BY CustomerID OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

依據客戶編號排序,跳過前面10筆記錄,取第10筆記錄。這很像Linq中的Skip.Take,Linq語法例子如下

var customers=customerList.Skip(10).Take(10);

異常處理 Exception Handling

SQL Server 2005引入了類似於.NET語言的異常處理機制到T-SQL代碼中,請參考下面的例子

BEGIN TRY
    BEGIN TRANSACTIONStart the transaction

    -- Delete the Customer
    DELETE FROM Customers
    WHERE EmployeeID = ‘CACTU’

    -- Commit the change
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    -- There is an error
    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION

    -- Raise an error with the details of the exception
    DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int
    SELECT @ErrMsg = ERROR_MESSAGE(),
        @ErrSeverity = ERROR_SEVERITY()

    RAISERROR(@ErrMsg, @ErrSeverity, 1)
END CATCH

如果在catch語句塊中捕獲了異常,只能引用RaiseError函數來繼續拋出異常。新版本的SQL Server引入了throw關鍵字,可取代RaiseError函數的作用。參考代碼如下

BEGIN TRY
    BEGIN TRANSACTION -- Start the transaction

    -- Delete the Customer
    DELETE FROM Customers
    WHERE EmployeeID = ‘CACTU’

    -- Commit the change
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    -- There is an error
    ROLLBACK TRANSACTION

    -- Re throw the exception
    THROW
END CATCH

異常處理機制的一個好處是N層回滾(rollback),拋出異常的程序,逐層向上尋找,直到找到處理異常的代碼。

存儲過程執行改善 Execute Procedure Enhanced

在舊的SQL Server版本中,要返回一個查詢語句的列信息,可以使用SET FMTONLY語句,它返回結果列,而不是實際的數據,請參考運行下面的語句:

SET FMTONLY ON;
GO
SELECT *    FROM  dbo.GBITEM
GO
SET FMTONLY OFF;

存儲過程是一個預編譯的批處理語句塊,預編譯可改善性能,前一個版本的SQL Server應用關鍵字(WITH RECOMPILE) 可以強制重新編譯存儲過程,生成新的執行計劃。新版本的SQL Server改善了查詢結果的返回信息,可以對存儲過程的查詢結果,進行別名字義。下面的代碼,重新定義存儲過程的返回列信息:

EXEC CustOrderDetail ‘2’
WITH RESULT SETS
(
    (
    ProductName1 varchar(100),
    Unitprice1 varchar(100),
    Quantity1 varchar(100),
    Discount1 varchar(100),
    ExtendedPrice1 varchar(100)
    )
);

Exec的參數With Results Set可以依據存儲過程的實際返回結果,重新定義返回的列名或類型。參考下面的SQL語句:

CREATE PROCEDURE Denali_WithResultSet
AS
BEGIN 
       SELECT 1 as No,’Tsql’ Type, ‘WithResultSet’ AS Feature UNION ALL
       SELECT 2 as No,’Tsql’ Type, ‘Throw’ AS Feature UNION ALL
       SELECT 3 as No,’Tsql’ Type, ‘Offset’ AS Feature UNION ALL
       SELECT 4 as No,’Tsql’ Type, ‘SequenceAS Feature 
END
GO
EXEC Denali_WithResultSet 
WITH RESULT SETS
(
       (      No int,
              FeatureType varchar(50),
              FeatureName varchar(50)
       )  
) 
 

上面的代碼演示了如何運用with result set來修改存儲過程的返回列名稱。這個特性與第三方的工具集成,比如SSIS任務,報表中會有一定的改善作用。

元數據函數 Metadata Function

新版本的SQL Server增加了幾個存儲過程用於獲取SQL Server 對象的元數據,比如下面的SQL語句:

EXEC sp_describe_first_result_set @tsql=N‘SELECT * FROM gbitem‘

它會返回表gbitem的每一列的元數據信息,比如列名,是否可空,數據類型,排序等數據信息。

下面的例子演示了如何應用上面提到的函數,返回存儲過程的元數據:

CREATE PROC Production.TestProc
AS
SELECT Name, ProductID, Color FROM Production.Product ;
SELECT Name, SafetyStockLevel, SellStartDate FROM Production.Product ;
GO

SELECT * FROM sys.dm_exec_describe_first_result_set
(‘Production.TestProc‘, NULL, 0) ;

此函數還可以返回多個SQL批處理查詢的元數據信息,請參考下面的例子代碼

SELECT * FROM sys.dm_exec_describe_first_result_set(
N‘SELECT CustomerID, TerritoryID, AccountNumber FROM Sales.Customer WHERE CustomerID = @CustomerID;
SELECT * FROM Sales.SalesOrderHeader;‘,
N‘@CustomerID int‘, 0) AS a;
GO

如果一個存儲過程想返回多筆記錄集,在舊版本的SQL Server中,只能獲取最後一次返回的記錄集。新版本的SQL Server對此作出一些改善,可以指定要返回的記錄集。

CREATE PROC TestProc2
AS
SELECT object_id, name FROM sys.objects ;
SELECT name, schema_id, create_date FROM sys.objects ;
GO

SELECT * FROM sys.dm_exec_describe_first_result_set_for_object(OBJECT_ID(‘TestProc2‘), 0) ;
SELECT * FROM sys.dm_exec_describe_first_result_set_for_object(OBJECT_ID(‘TestProc2‘), 1) ;
GO

這個特性會給程序處理上帶來很多便利,為返回二個結果集而不必定義二個重復的存儲過程,而僅僅是返回的結果不同。

SQL 函數 SQL Function

新版本的SQL Server增加了很多函數,請參考園友的文章SQL Server 2012新增的內置函數嘗試

這些函數的到來,可以給SQL編程帶來便利性。不過,我以為自從SQL Server 2005引入了CLR,實現這些函數都相當容易,直接對.NET BCL一層簡單的封裝即可,不知道為何過了二個重要的版本後(SQL Server 2008,SQL Server 2008 R2),才加入這些基礎函數。

關於SQL Server 2012 T-SQL方面更多的特性,請參考這裏:

http://dattatreysindol.com/2012/07/30/sql-server-2012-transact-sql-enhancements-learning-resources/

SQL Server 2012 T-SQL 新特性