當我們浏覽SQL Server 2008的新特性的時候,我們發現一個很有趣的特性叫做表值參數(Table-Valued Parameter)。你能否給我們詳細介紹一下我們可以如何利用這個新特性嗎?
專家解答:
表值參數確實是SQL Server 2008的一個新特性。顧名思義,表值參數表示你可以把一個表類型作為參數傳遞到函數或存儲過程裡。更高級的功能方面,表值參數的功能可以允許你向被聲明為T-SQL變量的表中導入數據,然後把該表作為一個參數傳遞到存儲過程或函數中去。表值參數的優點在於你可以向存儲過程或函數發送多行數據,而無需向以前那樣必須聲明多個參數或者使用XML參數類型來處理多行數據。據說,表值參數可以處理多達1000行數據。
我們在這裡將會介紹表值參數,並舉一些簡單的編碼例子來演示如何通過使用表值參數來完成以下任務:
創建可以作為表值參數傳遞到函數或存儲過程的表類型
創建使用表值參數的存儲過程
聲明表類型,向該表導入數據,並把它傳遞到存儲過程裡
在數據倉庫應用程序裡的數據加載過程,我們一般會在維度處理過程中把源系統鍵對應到代理鍵;然後使用代理鍵來識別數據倉庫中的維度行。這樣對維度行進行的每一個改動都會存儲在一行帶有新代理鍵的新行中,我們就可以保存維度行的完整歷史記錄。當對維度行進行改動或添加新行時,我們只需要給源系統鍵添加一個新的代理鍵並在維度表裡插入新的一行就可以了。在處理事實行(fact rows)時,我們查找代理鍵並將其存儲在事實表中。查詢通過代理鍵連接事實表和維度表。由於多個事實表通常會索引至同一個維度(例如Customer),代理鍵查找功能可以給我們提供一個使用表值參數的很好的例子。我們可以在存儲過程中執行一次代理鍵查找,然後在多個事實表的數據載入過程中調用這個代理鍵查找。
除了簡單的查找源系統鍵的代理鍵之外,還有一種情況可利用表值參數,即事實表含有一個不存在於維度表的源系統鍵。在這種情況下,我們則想要在維度裡創建一個推斷成員(Inferred member),也就是說,創建一個新的代理鍵並把它添加到維度裡,在我們從源系統裡獲得真正的維度行之後再把它替換更新掉。
下面的演示編碼只在SQL Server 2008的二月份社區測試試用版中進行過測試。
新建一個表類型
為了把表作為一個參數傳遞到存儲過程或函數中,你首先要創建一個TABLE TYPE,如下所示:
以下是引用片段:
CREATETYPESourceKeyListASTABLE(
SourceKeyNVARCHAR(50)
)
GO
T-SQL編碼跟新建一個普通的表的編碼非常相似。你可以查詢當前數據庫的sys.types來確定已創建的任何表類型:
以下是引用片段:
SELECTname,system_type_id,user_type_id
FROMsys.types
WHEREis_table_type=1
新建一個帶有表值參數的存儲過程
我們要創建一個存儲過程,該存儲過程執行代理鍵查找命令,如果源鍵不存在則添加一個推理成員。首先我們需要新建一個維度表樣例:
以下是引用片段:
CREATETABLEdbo.dim_Customer(
sk_CustomerINTIDENTITYNOTNULL,
CustomerSourceKeyNVARCHAR(50)NOTNULL,
CustomerNameNVARCHAR(50)NOTNULL,
InferredMemberBITNOTNULL
)
代理鍵是整數類型,我們使用IDENTITY屬性來自動分配插入行的序列號。當我們插入一行源鍵不存在的行時,InferredMember列設置為1。當我們在維度處理過程中從源系統中獲得該行後,它將替換掉推理成員行,而InferredMember列的值會變成0。
現在我們來創建一個接受新建表類型作為參數並執行代理鍵查找和推理處理的存儲過程:
以下是引用片段:
CREATEPROCEDUREdbo.stp_GetCustomerSK
@source_key_listSourceKeyListREADONLY
AS
BEGIN
INSERTINTOdbo.dim_Customer(
CustomerSourceKey,CustomerName,InferredMember
)
SELECTSourceKey,N'INFERRED',1
FROM@source_key_listk
LEFTJOINdbo.dim_CustomercONc.CustomerSourceKey=k.SourceKey
WHEREsk_CustomerISNULL
SELECTsk_Customer,CustomerSourceKey
FROMdbo.dim_Customerc
JOIN@source_key_listkONk.SourceKey=c.CustomerSourceKey
END
GO
表值參數必須被聲明為READONLY。你不能對表值參數執行任何DML(即插入、更新、刪除)。你職能在SELECT語句裡引用它。存儲過程把表值參數與客戶維度連接起來,查找出任何還不存在的源鍵,然後插入這些鍵。然後存儲過程再把表值參數與客戶維度連接來返回含有源鍵及其對應代理鍵的結果集。
你可以通過查詢sys.parameters來查看任何被聲明為READONLY的參數:
以下是引用片段:
SELECTobject_id,nameFROMsys.parameters
WHEREis_readonly=1
GO
聲明表值參數,導入數據,並把它傳遞到存儲過程裡
你聲明一個表類型的T-SQL變量,使用INSERT插入語句向該表導入數據:
以下是引用片段:
DECLARE@source_key_listSourceKeyList
INSERTINTO@source_key_list
SELECT'CustomerID_001'UNIONALL
SELECT'CustomerID_002'UNIONALL
SELECT'CustomerID_003'
EXECdbo.stp_GetCustomerSK@source_key_list
GO
為了演示的目的,上面的SELECt語句只是硬編碼一些值來插入;你通常可以從你的源系統表裡執行SELECT DISTINCT命令來獲得你希望對其執行代理鍵查找功能的源系統鍵的列表。上面腳本返回的結果應該如下圖所示:
返回結果顯示了每一個源鍵的代理鍵。