我有一个表,其中有一列的值来自枚举。我需要创建一个 TSQL 函数,以便在检索时将这些值转换为“友好名称”。
例子:
'DateOfBirth' --> 'Date Of Birth'
'PrincipalStreetAddress' --> 'Principal Street Address'
我需要一个直接的 TSQL UDF 解决方案。我没有安装扩展存储过程或 CLR 代码的选项。
我有一个表,其中有一列的值来自枚举。我需要创建一个 TSQL 函数,以便在检索时将这些值转换为“友好名称”。
例子:
'DateOfBirth' --> 'Date Of Birth'
'PrincipalStreetAddress' --> 'Principal Street Address'
我需要一个直接的 TSQL UDF 解决方案。我没有安装扩展存储过程或 CLR 代码的选项。
/*
Try this. It's a first hack - still has problem of adding extra space
at start if first char is in upper case.
*/
create function udf_FriendlyName(@PascalName varchar(max))
returns varchar(max)
as
begin
declare @char char(1)
set @char = 'A'
-- Loop through the letters A - Z, replace them with a space and the letter
while ascii(@char) <= ascii('Z')
begin
set @PascalName = replace(@PascalName, @char collate Latin1_General_CS_AS, ' ' + @char)
set @char = char(ascii(@char) + 1)
end
return LTRIM(@PascalName) --remove extra space at the beginning
end
如果您使用的是 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 不能影响数据库,所以你不能注册正则表达式 com 对象,这样就放弃了这个想法。但是,存储过程可以 - 所以这可能是一条路线。
为了进行区分大小写的比较,您必须将查询的排序规则设置为区分大小写,然后使用我认为的替换...这里有一篇文章可能有助于在正确的方向:
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 + 可能需要的空格数相同的字符串。在我的例子中,我把它翻了一番。
不是最优雅的解决方案,但它有效:
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
我发现这完全符合要求。由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!