Преобразование строки PascalCase в понятное имя в TSQL

У меня есть таблица со столбцом, значения которого взяты из перечисления. Мне нужно создать функцию TSQL для преобразования этих значений в «понятные имена» при извлечении.

Примеры:

 'DateOfBirth' --> 'Date Of Birth'
 'PrincipalStreetAddress' --> 'Principal Street Address'

Мне нужно прямое решение TSQL UDF. У меня нет возможности установить расширенные процедуры хранения или код CLR.


person Jose Basilio    schedule 07.05.2009    source источник
comment
+1 просто за то, что столкнулся с этой проблемой!   -  person Joseph    schedule 08.05.2009


Ответы (5)


Если вы используете SQL Server 2005, вы можете написать собственную процедуру CLR:

static string ToFriendlyCase(this string PascalString)
{
    return Regex.Replace(PascalString, "(?!^)([A-Z])", " $1");
}

Выходы:

Преобразуйте мой приговор с сумасшедшим падежом Паскаля в дружественный кейс

Если вы не используете 2005, то вам придется либо проанализировать его вручную, либо ссылаться на объект регулярного выражения, используя расширенные процедуры. Хорошую статью можно найти здесь:

http://www.codeproject.com/KB/mcpp/xpregex.aspx

Изменить: UDF не может повлиять на базу данных, поэтому вы не можете зарегистрировать объект regex com, что исключает эту идею. Однако хранимая процедура может - так что это может быть маршрут.

Чтобы сделать сравнение с учетом регистра, вам нужно будет настроить параметры сортировки для запроса с учетом регистра, а затем использовать замену, я думаю ... вот статья, которая может быть полезна, чтобы указать на вас в правильное направление:

http://www.mssqltips.com/tip.asp?tip=1032

person BenAlabaster    schedule 07.05.2009
comment
Мне нужно использовать прямой TSQL UDF. Для меня функция CLR не подходит. - person Jose Basilio; 08.05.2009
comment
Хм, мерзко, я не уверен, можно ли это сделать с помощью UDF ... потому что UDF не может повлиять на базу данных, поэтому вы не можете зарегистрировать библиотеку регулярных выражений. Вам нужно будет сделать это через сохраненную процедуру. Я почти уверен, что вам придется разбирать его вручную. - person BenAlabaster; 08.05.2009
comment
Это также проскользнет XML в X M L. : / Я бы посоветовал: new Regex( @" (?<=[A-Z])(?=[A-Z][a-z]) | (?<=[^A-Z])(?=[A-Z]) | (?<=[A-Za-z])(?=[^A-Za-z])", RegexOptions.IgnorePatternWhitespace - person Custodio; 18.05.2011

Не самое элегантное решение, но работает:

declare @pascalCasedString nvarchar(max) = 'PascalCasedString'
declare @friendlyName nvarchar(max) = ''
declare @currentCode int;
declare @currentChar nvarchar;

while (LEN(@pascalCasedString) > 0)
    begin
        set @currentCode = UNICODE(@pascalCasedString)
        set @currentChar = NCHAR(@currentCode)

        if ((@currentCode >= 65) AND (@currentCode <= 90))
        begin
            set @friendlyName += SPACE(1)
        end
        set @friendlyName +=  @currentChar
        set @pascalCasedString = RIGHT(@pascalCasedString,LEN(@pascalCasedString) - 1)
    end

select @friendlyName
person Colin Cochrane    schedule 07.05.2009
comment
Этот код не компилируется в SQL Server. Я предполагаю, что это либо PLSQL, либо MySQL. - person Jose Basilio; 08.05.2009
comment
Думаю, этот код должен работать. Сделайте его совместимым с TSQL, и я дам вам голос. - person ichiban; 08.05.2009
comment
При дальнейшем осмотре я обнаружил, что синтаксис работает в SQL Server 2008, но не работает в более старых версиях. Тем не менее. +1 - person Jose Basilio; 08.05.2009


declare @arg varchar(20)
set @arg = 'DateOfBirthOnMonday'

declare @argLen int
set @argLen = len(@arg)

declare @output varchar(40)
set @output = ''

declare @i int
set @i = 1

declare @currentChar varchar(1)
declare @currentCharASCII int

while (1 = 1)
begin
set @currentChar = substring(@arg, @i, 1)
set @currentCharASCII = ascii(@currentChar)

if (@currentCharASCII >= 65 and @currentCharASCII <= 90)
set @output = @output + ' ' 

set @output = @output + @currentChar

set @i = @i+ 1

if (@i > @argLen) break
end

set @output = ltrim(rtrim(@output))
print @output

Измените значение @arg на то, с чем вы хотите протестировать.

Кроме того, вам может потребоваться изменить объявление @output для размещения строки, имеющей ту же длину, что и @arg + количество пробелов, которые могут потребоваться. В моем примере я увеличил его вдвое.

person shahkalpeshp    schedule 07.05.2009
comment
@Shahkalpesh - синтаксическая ошибка в строке с: (@currentCharASCII ›= 65 и @currentCharASCII @argLen) - person Jose Basilio; 08.05.2009
comment
Я тоже это тестировал. Он не компилируется. -1 - person ichiban; 08.05.2009
comment
ТАК съел ‹= знак. Я снова отформатировал пост. Теперь все должно быть в порядке. - person shahkalpeshp; 08.05.2009

Я обнаружил, что это работает именно так, как требуется. Любезно предоставлено SqlAuthority.com:

CREATE FUNCTION dbo.udf_TitleCase (@InputString VARCHAR(4000) )
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE @Index INT
DECLARE @Char CHAR(1)
DECLARE @OutputString VARCHAR(255)
SET @OutputString = LOWER(@InputString)
SET @Index = 2
SET @OutputString =
STUFF(@OutputString, 1, 1,UPPER(SUBSTRING(@InputString,1,1)))
WHILE @Index <= LEN(@InputString)
BEGIN
SET @Char = SUBSTRING(@InputString, @Index, 1)
IF @Char IN (' ', ';', ':', '!', '?', ',', '.', '_', '-', '/', '&','''','(')
IF @Index + 1 <= LEN(@InputString)
BEGIN
IF @Char != ''''
OR
UPPER(SUBSTRING(@InputString, @Index + 1, 1)) != 'S'
SET @OutputString =
STUFF(@OutputString, @Index + 1, 1,UPPER(SUBSTRING(@InputString, @Index + 1, 1)))
END
SET @Index = @Index + 1
END
RETURN ISNULL(@OutputString,'')
END

Использование:

SELECT dbo.udf_TitleCase('This function will convert this string to title case!')

Вывод:

This Function Will Convert This String To Title Case!
person Rebecca    schedule 03.12.2013

person    schedule
comment
После добавления SUBSTRING, чтобы удалить лишнее пространство, он работает как шарм. Спасибо! - person Jose Basilio; 08.05.2009
comment
Небольшое предложение: вместо последнего return SUBSTRING (@ PascalName, 2, LEN (@PascalName)) - удалить пробел в начале, вы могли бы использовать return LTrim (@PascalName) Не имеет большого значения в это случай, но в целом он удаляет начальные пробелы (независимо от их количества), но не удаляет любые другие возможные символы, отличные от пробела. - person M.Turrini; 08.05.2009
comment
@Turro - Отличный совет. В то время я не думал об этом, но обновил сейчас. Спасибо! - person Jose Basilio; 08.05.2009