2011-01-07 42 views
4

我試圖清理數據在我們的數據庫中的「名稱」字段和分割解析數據這些數據轉化爲姓,中間名,姓氏&。目前,我使用Case語句在文本內查找各種觸發器,以幫助我以某種方式格式化輸出。如何遞歸在SQL語句

不過,我開始注意到,我中嵌套等檢查測試和需要弄清楚如何處理遞歸數據。看到我如何抽取名字的這個例子。

Case 
    When CharIndex(' ',LTrim(RTrim(Name))) in (0,1) Then '' --'empty or LName' 
    When Left(Name,3) IN ('MR ','MS ', 'DR ','MRS') Then --'Prefix Titles' 
    Case --'If we found a prefix, run the same "tests" with the prefix removed' 
     When CharIndex(' ',LTrim(RTrim(Right(Name,Len(Name)-CharIndex(' ',Name))))) 
     in (0,1) Then '' 
     When SubString(LTrim(RTrim(Right(Name,Len(Name)-CharIndex(' ',Name)))),3,1) 
     = '&' Then SubString(LTrim(RTrim(Right(Name,Len(Name)-CharIndex(' ', 
     Name)))),1,5) 
     Else Left(LTrim(RTrim(Right(Name,Len(Name)-CharIndex(' ',Name)))), 
     CHarIndex(' ',LTrim(RTrim(Right(Name,Len(Name)-CharIndex(' ',Name)))))-1) 
    End 
    When SubString(LTrim(RTrim(Name)),3,1) = '&' Then 
    SubString(LTrim(RTrim(Name)),1,5) --'Look for initials e.g. J & A Smith' 
    Else Left(LTrim(RTrim(Name)),CHarIndex(' ',LTrim(RTrim(Name)))-1) 
    End 

因此,爲了得到這個工作在更復雜的情況(例如MR JOHN A SMITH JR),我需要遞歸測試。在命令式編程,我會做這樣的事情,如果我有一個名爲GetFirstName功能:

GetFirstName('MR JOHN A SMITH JR') 
//GetFirstName identfies 'MR' and within the function it calls: 
|| 
\\ 
    ==> GetFirstName('JOHN A SMITH JR') 
     //GetFirstName identifies 'JR' and within the function it calls: 
     || 
     \\ 
      ==> GetFirstName('JOHN A SMITH') 
       //Finally, it returns 'JOHN' 

理想的情況下,這將是巨大爲此在直SQL,但我不知道這是可能的。如果我不使用直接的SQL,會有什麼替代方法? (我使用SQL Server 2005)

+3

這是一個在應用程序代碼而不是SQL中更好處理的任務。 – 2011-01-07 19:21:40

回答

1

我不認爲這是一些容易/清潔直SQL完成。您可以使用正則表達式,但是您必須編寫自己的CLR函數來提供正則表達式功能。

0

這聽起來像是一次性活動。你確定你在使用臨時表的幾個語句中不能這麼做嗎?如果這是一次性活動,那麼您可能比代碼性能更需要準確性和簡單的代碼調試。

考慮這樣的事情:

 
CREATE TABLE #MyNames (
    PersonID INT PRIMARY KEY, 
    OriginalName VARCHAR(50), 
    WorkingName VARCHAR(50), 
    CandidateTitle VARCHAR(10), 
    CandidateLastName VARCHAR(50), 
    CandidateFirstName VARCHAR(50), 
    CandidateMiddleName VARCHAR(50) 
    --Your other candidate fields..... 
) 

INSERT INTO #MyNames (PersonID, OriginalName) 
SELECT TOP 100 ID, LTRIM(RTRIM(Name)) from SourcePersonTable 

--Possibly add some indexes here for original name 

UPDATE #MyNames 
SET CandidateTitle = LEFT(OriginalName,3), 
    WorkingName = SUBSTRING(OriginalName,4,9999) 
Where LEFT(OriginalName,3) IN 
    ('MR ','MRS','MS ','DR ') 

-- etc... 

只要保持添加步驟和編輯[WorkingName]字段。當你有一個通做,只是做...

 
UPDATE #MyNames SET WorkingName = OriginalName 

...你準備做另一個橫掃。

+0

感謝您的建議。我想使用臨時表是一種可能性,但它迫使我多次編寫代碼。由於名稱字段的內容可能同時觸發多個「規則」,因此在我看來,遞歸實現將是有利的。 – 2011-01-08 16:05:13