2011-12-28 24 views
2

我想知道一個示例,它顯示瞭如何創建一個UDF或存儲過程,該過程從Superkey/Subtable返回完整的行SQL Server數據庫(最好是2005年,但2008年會好的)。如何創建一個在SuperKey,SubTable數據庫中返回完整行的UDF

具體而言,讓我們假設主表名爲SecurityMaster其中有一個SecurityID PK。我們也可以想象最後一列是SecurityType,它定義了更詳細信息所在的表。讓我們想象SecurityMaster表如下:

SecurityID Name   Currency SecurityType 
---------- ----------- -------- ------------ 
1   BP Plc  GBP  Equity 
2   MSFT C30 12 USD  EquityOption 
3   Greek 6% 20 EUR  Bond 

進一步讓我們想象EquityOption表如下所示

SecurityID PutCall Strike Maturity 
---------- ------- ------ -------- 
2   Call  30  Jun 2012 

讓我們也可以想象Bond表如下所示:

SecurityID Coupon Maturity 
---------- ------ ----------- 
3   0.06  15 Mar 2020 

我想要一個'方法'(無論是Proc或UDF),返回以下連接表:

SELECT * FROM MyFuncOrProc(2) 

導致類似的輸出:

SecurityID Name   Currency SecurityType SecurityID PutCall Strike Maturity 
---------- ----------- -------- ------------ ---------- ------- ------ -------- 
2   MSFT C30 12 USD  EquityOption 2   Call  30  Jun 2012 

的想法在這裏是,我想

  1. 具有超大SecurityMaster疏表避免(想象50種安全類型)
  2. 具有需要較少存儲空間的數據的緊湊表示
  3. FK在子表中級聯更新和刪除強制參照完整性
  4. 我可以提供傳遞給Execute命令的動態SQL字符串,但我不知道如何使返回的行可用於調用方。想象一下,你想使用結果集來執行另一個連接?
  5. 如果子表不(在Equity的情況下)存在,則意味着安全完全被SecurityMaster

P.S.僅指定請不要關閉此問題,直到提供完整示例或對示例的引用。

p.p.s有人提到這可能能夠使用一些sys表或列來完成,但它對我來說並不明顯如何做到這一點,因此是一個問題。

非常感謝,在此先行和親切的問候,

伯蒂。

回答

0

只要表的數量是有限的,你可以join在一起:

select * 
from SecurityMaster sm 
left join 
     EquityOption eo 
on  sm.SecurityType = 'EquityOption' 
     and sm.SecurityID = eo.SecurityID 
left join 
     Bond b 
on  sm.SecurityType = 'Bond' 
     and sm.SecurityID = b.SecurityID 

這是不尋常的被完全省略了SecurityType列。如果Bond表中存在SecurityID,則可以判斷證券是否爲債券。

+0

感謝這裏的指針,但這個例子並沒有利用sm.SecurityType中可用的表名查找的事實。如果有50個子表,這是否是一個痛苦的解決方案?如果沒有其他方法,那麼我將需要寫出50個連接。如果更簡潔(易於理解的初學者解決方案)是不可能的,我會非常驚訝。非常感謝, – Bertie 2011-12-28 19:25:21

+0

你將如何處理五十個連接?如果是報表,請將所有可報告列移到主表中。如果這留下了一些列是空的沒關係。 SQL Server非常有效地處理空列。 – Andomar 2011-12-28 19:32:03

+0

這種類型的Select語句將用於提供其他函數,Procs或CTE。創建彙總信息的視圖也很有用。我唯一不喜歡的方法是在結果集中顯示49個Subtables以及所需的Subtable。在結果中存在重複的列名稱會導致進一步的DML出現問題。設計子表格的最佳方法是什麼,以便在子表格中沒有共同的ColumnNames?非常感謝 – Bertie 2011-12-29 09:15:35

0

創建簡單的類似開關的過程,就像一個例子。

Create proc getFullSecurity 
@SecurityId int 
As 
Begin 
Declare @secType nvarchar(128) 

select @secType =SecurityType 
From securitymaster 
Where [email protected] 

If @sectype = 'equity' 
Select join with equity table 
Else if @sectype = 'something' 
Select join with something 
... 
End 

可以預取所有需要的領域進入第一次查詢變量 - 那麼你需要不加入與主表中的每一下一個選擇STMS。只需使用預取變量。

+0

感謝Oleg的評論。唯一的問題是你的代碼需要50條Elseif語句。如果沒有解決這個問題,那麼我將不得不認爲這是一個解決方案,但我更喜歡使用動態引用TableName或Sys表中的某些東西(如果可能的話)。僅供參考,我收到了類似問題的答案。親切的問候,http://dba.stackexchange.com/questions/9809/how-to-implement-superkey-sub-key-method-on-cascading-tables – Bertie 2011-12-28 19:31:34

+0

這將比動態查詢更快,並將保持您的過程緩存規模相對較低 – 2011-12-28 19:33:31

0
CREATE FUNCTION My_Function (@SecurityID Int) 
RETURNS TABLE 
AS 
RETURN 
(
      select * 
      from SecurityMaster A 
      left join EquityOption B on A.SecurityType = N'EquityOption' and B.SecurityID = A.SecurityID 
      left join Bond C on A.SecurityType = N'Bond' and C.SecurityID = A.SecurityID 
      Where A.SecurityID = @SecurityID 
) 
GO 
相關問題