SQL Server: 将所有大小写转换为正确的大小写/标题大小写

我有一个表,是导入为所有大写,我想把它变成正确的情况下。你们用什么剧本完成的?

369151 次浏览

这里有一个 UDF 可以解决这个问题。

create function ProperCase(@Text as varchar(8000))
returns varchar(8000)
as
begin
declare @Reset bit;
declare @Ret varchar(8000);
declare @i int;
declare @c char(1);


if @Text is null
return null;


select @Reset = 1, @i = 1, @Ret = '';


while (@i <= len(@Text))
select @c = substring(@Text, @i, 1),
@Ret = @Ret + case when @Reset = 1 then UPPER(@c) else LOWER(@c) end,
@Reset = case when @c like '[a-zA-Z]' then 0 else 1 end,
@i = @i + 1
return @Ret
end

但是,您仍然必须使用它来更新您的数据。

这个功能:

  • “正确的情况”所有“大写的情况下”的话,是由白色的空格分隔
  • 只剩下“小写单词”了
  • 即使是非英文字母也能正常使用
  • is portable in that it does not use fancy features of recent SQL server versions
  • can be easily changed to use NCHAR and NVARCHAR for unicode support,as well as any parameter length you see fit
  • white space definition can be configured
CREATE FUNCTION ToProperCase(@string VARCHAR(255)) RETURNS VARCHAR(255)
AS
BEGIN
DECLARE @i INT           -- index
DECLARE @l INT           -- input length
DECLARE @c NCHAR(1)      -- current char
DECLARE @f INT           -- first letter flag (1/0)
DECLARE @o VARCHAR(255)  -- output string
DECLARE @w VARCHAR(10)   -- characters considered as white space


SET @w = '[' + CHAR(13) + CHAR(10) + CHAR(9) + CHAR(160) + ' ' + ']'
SET @i = 1
SET @l = LEN(@string)
SET @f = 1
SET @o = ''


WHILE @i <= @l
BEGIN
SET @c = SUBSTRING(@string, @i, 1)
IF @f = 1
BEGIN
SET @o = @o + @c
SET @f = 0
END
ELSE
BEGIN
SET @o = @o + LOWER(@c)
END


IF @c LIKE @w SET @f = 1


SET @i = @i + 1
END


RETURN @o
END

Result:

dbo.ToProperCase('ALL UPPER CASE and    SOME lower ÄÄ ÖÖ ÜÜ ÉÉ ØØ ĈĈ ÆÆ')
-----------------------------------------------------------------
All Upper Case and      Some lower Ää Öö Üü Éé Øø Cc Ææ

我想你会发现以下方法更有效:

IF OBJECT_ID('dbo.ProperCase') IS NOT NULL
DROP FUNCTION dbo.ProperCase
GO
CREATE FUNCTION dbo.PROPERCASE (
@str VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
SET @str = ' ' + @str
SET @str = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( @str, ' a', ' A'), ' b', ' B'), ' c', ' C'), ' d', ' D'), ' e', ' E'), ' f', ' F'), ' g', ' G'), ' h', ' H'), ' i', ' I'), ' j', ' J'), ' k', ' K'), ' l', ' L'), ' m', ' M'), ' n', ' N'), ' o', ' O'), ' p', ' P'), ' q', ' Q'), ' r', ' R'), ' s', ' S'), ' t', ' T'), ' u', ' U'), ' v', ' V'), ' w', ' W'), ' x', ' X'), ' y', ' Y'), ' z', ' Z')
RETURN RIGHT(@str, LEN(@str) - 1)
END
GO

替换语句可以直接剪切和粘贴到 SQL 查询中。它非常丑陋,但是通过将@str 替换为您感兴趣的列,您将不会为隐式游标付出代价,就像您对这样发布的 udfs 所付出的代价一样。我发现即使使用我的 UDF 也要高效得多。

哦,不要手动生成替换语句,而是使用下面的代码:

-- Code Generator for expression
DECLARE @x  INT,
@c  CHAR(1),
@sql    VARCHAR(8000)
SET @x = 0
SET @sql = '@str' -- actual variable/column you want to replace
WHILE @x < 26
BEGIN
SET @c = CHAR(ASCII('a') + @x)
SET @sql = 'REPLACE(' + @sql + ', '' ' + @c+  ''', '' ' + UPPER(@c) + ''')'
SET @x = @x + 1
END
PRINT @sql

无论如何,这取决于行的数量。我希望你可以只做 s/b ([ a-z ])/uc $1/,但是我们用我们现有的工具工作。

注意,您必须使用它,因为您必须将它用作... . SELECTdbo。ProperCase (LOWER (column)) ,因为该列为大写。它实际上在我的有5000个条目(甚至不到一秒)的表中工作得非常快,即使使用较低的条目。

针对关于国际化的大量评论,我提出了下面的实现,它仅仅依赖于 SQL Server 的上下级实现来处理每个 ascii 字符。记住,我们在这里使用的变量是 VARCHAR,这意味着它们只能保存 ASCII 值。为了使用更多的国际字母,必须使用 NVARCHAR。逻辑是相似的,但是您需要使用 UNICODE 和 NCHAR 来代替 ASCII 和 CHAR,并且替换语句将更加庞大... ..。

-- Code Generator for expression
DECLARE @x  INT,
@c  CHAR(1),
@sql    VARCHAR(8000),
@count  INT
SEt @x = 0
SET @count = 0
SET @sql = '@str' -- actual variable you want to replace
WHILE @x < 256
BEGIN
SET @c = CHAR(@x)
-- Only generate replacement expression for characters where upper and lowercase differ
IF @x = ASCII(LOWER(@c)) AND @x != ASCII(UPPER(@c))
BEGIN
SET @sql = 'REPLACE(' + @sql + ', '' ' + @c+  ''', '' ' + UPPER(@c) + ''')'
SET @count = @count + 1
END
SET @x = @x + 1
END
PRINT @sql
PRINT 'Total characters substituted: ' + CONVERT(VARCHAR(255), @count)

Basically the premise of the my method is trading pre-computing for efficiency. The full ASCII implementation is as follows:

IF OBJECT_ID('dbo.ProperCase') IS NOT NULL
DROP FUNCTION dbo.ProperCase
GO
CREATE FUNCTION dbo.PROPERCASE (
@str VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
SET @str = ' ' + @str
SET @str =     REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@str, ' a', ' A'), ' b', ' B'), ' c', ' C'), ' d', ' D'), ' e', ' E'), ' f', ' F'), ' g', ' G'), ' h', ' H'), ' i', ' I'), ' j', ' J'), ' k', ' K'), ' l', ' L'), ' m', ' M'), ' n', ' N'), ' o', ' O'), ' p', ' P'), ' q', ' Q'), ' r', ' R'), ' s', ' S'), ' t', ' T'), ' u', ' U'), ' v', ' V'), ' w', ' W'), ' x', ' X'), ' y', ' Y'), ' z', ' Z'), ' š', ' Š'), ' œ', ' Œ'), ' ž', ' Ž'), ' à', ' À'), ' á', ' Á'), ' â', ' Â'), ' ã', ' Ã'), ' ä', ' Ä'), ' å', ' Å'), ' æ', ' Æ'), ' ç', ' Ç'), ' è', ' È'), ' é', ' É'), ' ê', ' Ê'), ' ë', ' Ë'), ' ì', ' Ì'), ' í', ' Í'), ' î', ' Î'), ' ï', ' Ï'), ' ð', ' Ð'), ' ñ', ' Ñ'), ' ò', ' Ò'), ' ó', ' Ó'), ' ô', ' Ô'), ' õ', ' Õ'), ' ö', ' Ö'), ' ø', ' Ø'), ' ù', ' Ù'), ' ú', ' Ú'), ' û', ' Û'), ' ü', ' Ü'), ' ý', ' Ý'), ' þ', ' Þ'), ' ÿ', ' Ÿ')
RETURN RIGHT(@str, LEN(@str) - 1)
END
GO

现在回去拿未上升的数据是不是太晚了?

冯 · 诺依曼,麦凯恩,德古兹曼和约翰逊 · 史密斯的客户群可能不会喜欢你的处理结果。

另外,我猜这是一次性的数据升级?导出、过滤/修改和重新导入修正后的名称到 db 中可能更容易,然后您可以使用非 SQL 方法来修改名称..。

我上面发布的链接是一个很好的选择,它解决了主要问题: 我们永远不能通过编程来解释所有的情况(Smith-Jones,von Haussen,John Smith M.D。) ,至少不能以一种优雅的方式。Tony 引入了异常/中断字符的概念来处理这些情况。 无论如何,基于 Cervo 的想法(所有较低字符的上部都在空格之前) ,可以用一个基于表的替换来包装 return 语句。实际上,任何低/高字符组合都可以插入到@alpha 中,语句不会改变:

declare @str    nvarchar(8000)
declare @alpha  table (low nchar(1), up nchar(1))




set @str = 'ALL UPPER CASE and    SOME lower ÄÄ ÖÖ ÜÜ ÉÉ ØØ ĈĈ ÆÆ'


-- stage the alpha (needs number table)
insert into @alpha
-- A-Z / a-z
select      nchar(n+32),
nchar(n)
from        dbo.Number
where       n between 65 and 90 or
n between 192 and 223


-- append space at start of str
set @str = lower(' ' + @str)


-- upper all lower case chars preceded by space
select  @str = replace(@str, ' ' + low, ' ' + up)
from    @Alpha


select @str

如果您可以在 SQL Server 中启用 CLR (需要2005年或更高版本) ,那么您可以使用 内置函数create a CLR function,它将允许您创建一种文化感知的方式,只需要几行代码就可以实现这一点。

Here is another variation I found on the SQLTeam.com Forums @ Http://www.sqlteam.com/forums/topic.asp?topic_id=47718

create FUNCTION PROPERCASE
(
--The string to be converted to proper case
@input varchar(8000)
)
--This function returns the proper case string of varchar type
RETURNS varchar(8000)
AS
BEGIN
IF @input IS NULL
BEGIN
--Just return NULL if input string is NULL
RETURN NULL
END


--Character variable declarations
DECLARE @output varchar(8000)
--Integer variable declarations
DECLARE @ctr int, @len int, @found_at int
--Constant declarations
DECLARE @LOWER_CASE_a int, @LOWER_CASE_z int, @Delimiter char(3), @UPPER_CASE_A int, @UPPER_CASE_Z int


--Variable/Constant initializations
SET @ctr = 1
SET @len = LEN(@input)
SET @output = ''
SET @LOWER_CASE_a = 97
SET @LOWER_CASE_z = 122
SET @Delimiter = ' ,-'
SET @UPPER_CASE_A = 65
SET @UPPER_CASE_Z = 90


WHILE @ctr <= @len
BEGIN
--This loop will take care of reccuring white spaces
WHILE CHARINDEX(SUBSTRING(@input,@ctr,1), @Delimiter) > 0
BEGIN
SET @output = @output + SUBSTRING(@input,@ctr,1)
SET @ctr = @ctr + 1
END


IF ASCII(SUBSTRING(@input,@ctr,1)) BETWEEN @LOWER_CASE_a AND @LOWER_CASE_z
BEGIN
--Converting the first character to upper case
SET @output = @output + UPPER(SUBSTRING(@input,@ctr,1))
END
ELSE
BEGIN
SET @output = @output + SUBSTRING(@input,@ctr,1)
END


SET @ctr = @ctr + 1


WHILE CHARINDEX(SUBSTRING(@input,@ctr,1), @Delimiter) = 0 AND (@ctr <= @len)
BEGIN
IF ASCII(SUBSTRING(@input,@ctr,1)) BETWEEN @UPPER_CASE_A AND @UPPER_CASE_Z
BEGIN
SET @output = @output + LOWER(SUBSTRING(@input,@ctr,1))
END
ELSE
BEGIN
SET @output = @output + SUBSTRING(@input,@ctr,1)
END
SET @ctr = @ctr + 1
END


END
RETURN @output
END






GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

下面是一个使用序列或数字表而不是循环的版本。您可以修改 WHERE 子句以适应您的个人规则,以确定何时将字符转换为大写。我只是包括了一个简单的设置,将大写的任何字母是由一个非字母除了撇号进行。这就意味着123apple 会在“ a”上有一个匹配,因为“3”不是一个字母。如果只需要空格(空格、制表符、回车符、换行符) ,则可以将模式 '[^a-z]'替换为 '[' + Char(32) + Char(9) + Char(13) + Char(10) + ']'


CREATE FUNCTION String.InitCap( @string nvarchar(4000) ) RETURNS nvarchar(4000) AS
BEGIN


-- 1. Convert all letters to lower case
DECLARE @InitCap nvarchar(4000); SET @InitCap = Lower(@string);


-- 2. Using a Sequence, replace the letters that should be upper case with their upper case version
SELECT @InitCap = Stuff( @InitCap, n, 1, Upper( SubString( @InitCap, n, 1 ) ) )
FROM (
SELECT (1 + n1.n + n10.n + n100.n + n1000.n) AS n
FROM       (SELECT 0 AS n UNION SELECT    1 UNION SELECT    2 UNION SELECT    3 UNION SELECT    4 UNION SELECT    5 UNION SELECT    6 UNION SELECT    7 UNION SELECT    8 UNION SELECT    9) AS    n1
CROSS JOIN (SELECT 0 AS n UNION SELECT   10 UNION SELECT   20 UNION SELECT   30 UNION SELECT   40 UNION SELECT   50 UNION SELECT   60 UNION SELECT   70 UNION SELECT   80 UNION SELECT   90) AS   n10
CROSS JOIN (SELECT 0 AS n UNION SELECT  100 UNION SELECT  200 UNION SELECT  300 UNION SELECT  400 UNION SELECT  500 UNION SELECT  600 UNION SELECT  700 UNION SELECT  800 UNION SELECT  900) AS  n100
CROSS JOIN (SELECT 0 AS n UNION SELECT 1000 UNION SELECT 2000 UNION SELECT 3000)                                                                                                             AS n1000
) AS Sequence
WHERE
n BETWEEN 1 AND Len( @InitCap )
AND SubString( @InitCap, n, 1 ) LIKE '[a-z]'                 /* this character is a letter */
AND (
n = 1                                                    /* this character is the first `character` */
OR SubString( @InitCap, n-1, 1 ) LIKE '[^a-z]'           /* the previous character is NOT a letter */
)
AND (
n < 3                                                    /* only test the 3rd or greater characters for this exception */
OR SubString( @InitCap, n-2, 3 ) NOT LIKE '[a-z]''[a-z]' /* exception: The pattern <letter>'<letter> should not capatolize the letter following the apostrophy */
)


-- 3. Return the modified version of the input
RETURN @InitCap


END

It would make sense to maintain a lookup of exceptions to take care of The von Neumann's, McCain's, DeGuzman's, and the Johnson-Smith's.

UPDATE titles
SET title =
UPPER(LEFT(title, 1)) +
LOWER(RIGHT(title, LEN(title) - 1))

Http://sqlmag.com/t-sql/how-title-case-column-value

我知道这是这个帖子的后期帖子,但是,值得一看。这个函数对我很有用。所以想分享一下。

CREATE FUNCTION [dbo].[fnConvert_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.fnConvert_TitleCase(Upper('ÄÄ ÖÖ ÜÜ ÉÉ ØØ ĈĈ ÆÆ')) as test
select dbo.fnConvert_TitleCase(upper('Whatever the mind of man can conceive and believe, it can achieve. – Napoleon hill')) as test

结果:

enter image description here

如果您在 SSIS 中导入具有混合大小写的数据,并且需要在正确大小写的情况下对列进行查找,那么您将注意到,在源混合且查找源正确的情况下,查找将失败。您还会注意到,对于派生列,不能使用左右函数是 SSIS for SQLServer2008r2。这里有一个适合我的解决方案:

UPPER(substring(input_column_name,1,1)) + LOWER(substring(input_column_name, 2, len(input_column_name)-1))

I am a little late in the game, but I believe this is more functional and it works with any language, including Russian, German, Thai, Vietnamese etc. 它会在’或-或. 或(或)或空格(显然:)之后使用大写字母。

CREATE FUNCTION [dbo].[fnToProperCase]( @name nvarchar(500) )
RETURNS nvarchar(500)
AS
BEGIN
declare @pos    int = 1
, @pos2   int


if (@name <> '')--or @name = lower(@name) collate SQL_Latin1_General_CP1_CS_AS or @name = upper(@name) collate SQL_Latin1_General_CP1_CS_AS)
begin
set @name = lower(rtrim(@name))
while (1 = 1)
begin
set @name = stuff(@name, @pos, 1, upper(substring(@name, @pos, 1)))
set @pos2 = patindex('%[- ''.)(]%', substring(@name, @pos, 500))
set @pos += @pos2
if (isnull(@pos2, 0) = 0 or @pos > len(@name))
break
end
end


return @name
END
GO

我知道细节决定成败(尤其是涉及到人们的个人数据时) ,如果名字大写恰当就更好了,但是上面这种麻烦就是为什么我们这些注重实效、有时间意识的人会使用下面这些名字:

SELECT UPPER('Put YoUR O'So oddLy casED McWeird-nAme von rightHERE here')

根据我的经验,人们看到自己的名字是没问题的... ... 即使是在一个句子的中间。

参考: 俄罗斯人用铅笔!

刚学了 InitCap()

下面是一些示例代码:

SELECT ID
,InitCap(LastName ||', '|| FirstName ||' '|| Nvl(MiddleName,'')) AS RecipientName
FROM SomeTable

This worked in SSMS:

Select Jobtitle,
concat(Upper(LEFT(jobtitle,1)), SUBSTRING(jobtitle,2,LEN(jobtitle))) as Propercase
From [HumanResources].[Employee]

借用并改进了@Richard Sayakanit 的回答。这个可以处理多个单词。和他的回答一样,这个代码不使用任何 UDF,只使用内置函数(STRING_SPLITSTRING_AGG) ,而且速度非常快。STRING_AGG需要 SQLServer2017,但是您总是可以使用 STUFF/XML技巧。不会处理每个异常,但可以很好地满足许多需求。

SELECT StateName = 'North Carolina'
INTO #States
UNION ALL
SELECT 'Texas'




;WITH cteData AS
(
SELECT
UPPER(LEFT(value, 1)) +
LOWER(RIGHT(value, LEN(value) - 1)) value, op.StateName
FROM   #States op
CROSS APPLY STRING_SPLIT(op.StateName, ' ') AS ss
)
SELECT
STRING_AGG(value, ' ')
FROM cteData c
GROUP BY StateName

If you know all the data is just a single word here's a solution. First update the column to all lower and then run the following

    update tableName set columnName =
upper(SUBSTRING(columnName, 1, 1)) + substring(columnName, 2, len(columnName)) from tableName

对@Galwegian 的回答稍作修改——将例如 St Elizabeth's变成 St Elizabeth'S

这种修改将撇号 -s 保持为小写,其中 s 出现在所提供的字符串的末尾,或者 s 后面跟着一个空格(只有在这种情况下)。

create function properCase(@text as varchar(8000))
returns varchar(8000)
as
begin
declare @reset int;
declare @ret varchar(8000);
declare @i int;
declare @c char(1);
declare @d char(1);


if @text is null
return null;


select @reset = 1, @i = 1, @ret = '';


while (@i <= len(@text))
select
@c = substring(@text, @i, 1),
@d = substring(@text, @i+1, 1),
@ret = @ret + case when @reset = 1 or (@reset=-1 and @c!='s') or (@reset=-1 and @c='s' and @d!=' ') then upper(@c) else lower(@c) end,
@reset = case when @c like '[a-za-z]' then 0 when @c='''' then -1 else 1 end,
@i = @i + 1
return @ret
end

结果是:

  • st elizabeth'sSt Elizabeth's
  • o'keefeO'Keefe
  • o'sullivanO'Sullivan

其他人的意见,不同的解决方案是更好的非英语输入仍然是这种情况。

最近不得不解决这个问题,并提出了以下几点,没有什么完全打击我想要的一切。这将做一个完整的句子,情况下的特殊字处理。我们还遇到了单个字符‘ words’的问题,很多简单的方法都能处理这个问题,但复杂的方法就不行了。单个返回变量,也没有循环或游标。

CREATE FUNCTION ProperCase(@Text AS NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS BEGIN


DECLARE @return NVARCHAR(MAX)


SELECT @return = COALESCE(@return + ' ', '') + Word FROM (
SELECT CASE
WHEN LOWER(value) = 'llc' THEN UPPER(value)
WHEN LOWER(value) = 'lp' THEN UPPER(value) --Add as many new special cases as needed
ELSE
CASE WHEN LEN(value) = 1
THEN UPPER(value)
ELSE UPPER(LEFT(value, 1)) + (LOWER(RIGHT(value, LEN(value) - 1)))
END
END AS Word
FROM STRING_SPLIT(@Text, ' ')
) tmp


RETURN @return
END

将您的数据复制粘贴到 MSWord 中,并使用内置的文本转换为“每个单词大写”。与原始数据进行比较以解决异常。看不出有什么办法可以绕过手动规避“ MacDonald”和“ IBM”类型的异常,但这就是我如何做到的 FWIW。

在 ServerServer2016和更新的服务器上,可以使用 STRING _ Split


with t as (
select 'GOOFYEAR Tire and Rubber Company' as n
union all
select 'THE HAPPY BEAR' as n
union all
select 'MONK HOUSE SALES' as n
union all
select 'FORUM COMMUNICATIONS' as n
)
select
n,
(
select ' ' + (
upper(left(value, 1))
+ lower(substring(value, 2, 999))
)
from (
select value
from string_split(t.n, ' ')
) as sq
for xml path ('')
) as title_cased
from t

例子

不幸的是,我提出了另一个功能。这一个似乎比大多数快,但只有大写的第一个字母的单词由空格分隔。我已经检查了输入是否为空,并且如果在字符串的中间有多个空格,那么它就可以工作。我交叉应用了长度函数这样就不用调用两次了。我原以为 SQLServer 会缓存该值。买者自慎。

CREATE OR ALTER FUNCTION dbo.ProperCase(@value varchar(MAX)) RETURNS varchar(MAX) AS
BEGIN
 

RETURN (SELECT STRING_AGG(CASE lv WHEN 0 THEN '' WHEN 1 THEN UPPER(value)
ELSE UPPER(LEFT(value,1)) + LOWER(RIGHT(value,lv-1)) END,' ')
FROM STRING_SPLIT(TRIM(@value),' ') AS ss
CROSS APPLY (SELECT LEN(VALUE) lv) AS reuse
WHERE @value IS NOT NULL)


END

这个功能对我很有用

create function [dbo].Pascal (@string varchar(max))
returns varchar(max)
as
begin
declare @Index int
,@ResultString varchar(max)


set @Index = 1
set @ResultString = ''


while (@Index < LEN(@string) + 1)
begin
if (@Index = 1)
begin
set @ResultString += UPPER(SUBSTRING(@string, @Index, 1))
set @Index += 1
end
else if (
(
SUBSTRING(@string, @Index - 1, 1) = ' '
or SUBSTRING(@string, @Index - 1, 1) = '-'
or SUBSTRING(@string, @Index + 1, 1) = '-'
)
and @Index + 1 <> LEN(@string) + 1
)
begin
set @ResultString += UPPER(SUBSTRING(@string, @Index, 1))
set @Index += 1
end
else
begin
set @ResultString += LOWER(SUBSTRING(@string, @Index, 1))
set @Index += 1
end
end


if (@@ERROR <> 0)
begin
set @ResultString = @string
end


return replace(replace(replace(@ResultString, ' ii', ' II'), ' iii', ' III'), ' iv', ' IV')
end

在 Oracle SQL 或 PostgreSQL 中,只需执行以下操作:

SELECT INITCAP(title) FROM data;

In SQL Server, define the function first as in below, then:

SELECT dbo.InitCap(title) FROM data;

定义 dbo InitCap () :

 -- Drop the function if it already exists
IF OBJECT_ID('dbo.InitCap') IS NOT NULL
DROP FUNCTION dbo.InitCap;
GO
 

-- Implementing Oracle INITCAP function
CREATE FUNCTION dbo.InitCap (@inStr VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @outStr VARCHAR(8000) = LOWER(@inStr),
@char CHAR(1),
@alphanum BIT = 0,
@len INT = LEN(@inStr),
@pos INT = 1;
 

-- Iterate through all characters in the input string
WHILE @pos <= @len BEGIN
 

-- Get the next character
SET @char = SUBSTRING(@inStr, @pos, 1);
 

-- If the position is first, or the previous characater is not alphanumeric
-- convert the current character to upper case
IF @pos = 1 OR @alphanum = 0
SET @outStr = STUFF(@outStr, @pos, 1, UPPER(@char));
 

SET @pos = @pos + 1;
 

-- Define if the current character is non-alphanumeric
IF ASCII(@char) <= 47 OR (ASCII(@char) BETWEEN 58 AND 64) OR
(ASCII(@char) BETWEEN 91 AND 96) OR (ASCII(@char) BETWEEN 123 AND 126)
SET @alphanum = 0;
ELSE
SET @alphanum = 1;
 

END
 

RETURN @outStr;
END
GO