來說說資料庫自訂函數的遞迴用法
先看
有這樣一張樹形結構表,
如:C18 數位攝像機 是在 C12 數位產品 類別下
而 C12 數位產品 又在C2 IT產品 類別下!
C2 IT產品 在 000(根節點下)
即分類為 C2 IT產品-C12 數位產品-C18 數位攝像機
現在假使有這樣一種需要 ,通過SQLserver平台,達到給定ClassID得到其所有父節點的ClassID,並且通過“_”串連起來!如 C18 的結果為 C2_C12_C18 如下表
可以看到 數位攝像機的Place欄位為 C2_C12_C18,欄位Place為識別欄位,需求中有一定的作用!
這樣,當我們添加一個分類時,除了指定基本資料外,還需要指定其Place,才可以順利添加一條記錄!
當時可以通過很多方法得到新添加記錄的Place,但假使現在的需求是通過SQL自訂遞迴函式來完成功能!
如何??給定ClassID(該資料可以通過添加時得到的@@identity 全域變數擷取) 得到Place!
看如下SQL語句/**//*
-------------------------------------------
項目:公司Cmwin產品庫
名稱: F_ContactAllParentPlaceByClassID
功能: 通過classID產生其Place 首碼。除自己的Place
連結其所有父ClassID
相關表:ClassTree_update
編寫:馮岩
時間:2007-11-22 11:22
-------------------------------------------
*/
CREATE function F_ContactAllParentPlaceByClassID
(
@classID varchar(15) --參數
)
returns varchar(500)
as
begin
declare @ParentClassID varchar(15) --變數父ID
declare @Place varchar(500) --變數Place
set @Place = ''
--首先根據傳入的ClassID擷取其父ID,ParentClassID
SELECT @ParentClassID = ParentClassID FROM ClassTree_update
where ClassID = @classID
/**//*到此,我們得到 其父ID 例如 C18 我們可以得到 C12 但問題還沒有完,
C12本身也還有父節點,即C2。我們還需要將C2取出,C2的父節點為000即為根節點。
至此結束。
因此,由此問題可以看出,這是一個遞迴過程,根據指定ClassID擷取其父ID。再
根據父ID繼續擷取父ID的父ID,一直遞迴,直至父ID為000為止!
因此下面實現SQL函數的遞迴 ,注意看
*/
if (@ParentClassID <> '000')--如果不是根節點
begin
-- 再將@ParentClassID父ID作為ClassID傳入 進行自調用
set @Place = dbo.F_ContactAllParentPlaceByClassID(@ParentClassID) + @ParentClassID+'_'
end
return @Place
end
已有詳細說明!運行看
留心一下,有的SQL版本運行上述SQL語句在dbo.F_ContactAllParentPlaceByClassID(@ParentClassID)會報錯。原因是,此時正的建立dbo.F_ContactAllParentPlaceByClassID函數,而還未建立,在又在此處調用dbo.F_ContactAllParentPlaceByClassID(@ParentClassID),因此會提示沒有這個對象,解決辦法是先去掉dbo.F_ContactAllParentPlaceByClassID(@ParentClassID)建立後再Alter修改 即可!我遇見過一次!
運行效果
給定'C18'即得到其所有父節點的Place 並且使用"_"連結起來,離要求已經很近了,只是最後再將C18連在其後就達到要求,C18又是已知的!ClassID欄位為遞增,在實際添加分類時可以通過@@identity變數擷取到!連在其後即是 C2_C12_C18_
至此,通過SQL自訂函數實現給定ClassID 拼截出其對應的Place標識符!
總結:這裡只是示範一下SQL自訂函數的用法,並且實現一個簡單的遞迴。當然,要實現這個功能,不一定要使用函數。我在此只是作為示範函數用法而講講!有時使用SQL函數還是很方便的!