2011-01-07 47 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