2011-01-07 3 views
4

Я пытаюсь очистить данные в поле «Имя» в нашей базе данных и разбить эти данные на FirstName, MiddleName, & LastName. В настоящее время я использую оператор Case для поиска различных триггеров внутри текста, чтобы помочь мне форматировать вывод определенным образом.Как рекурсивно анализировать данные в операторе SQL

Однако я начинаю замечать, что я тестировал тесты внутри других тестов и должен выяснить, как обрабатывать данные рекурсивно. См. Этот пример того, как я извлекаю FirstName.

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. –

ответ

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

Спасибо за предложение. Я полагаю, что использование временных таблиц - это возможность, но это заставляет меня писать код несколько раз. Поскольку содержимое поля имени может одновременно запускать несколько «правил», мне кажется, что рекурсивная реализация будет выгодной. –

Смежные вопросы