SQL Server:将所有大写字母变为正确大小写/标题大小写

Posted

技术标签:

【中文标题】SQL Server:将所有大写字母变为正确大小写/标题大小写【英文标题】:SQL Server: Make all UPPER case to Proper Case/Title Case 【发布时间】:2010-09-18 19:28:32 【问题描述】:

我有一个导入为全大写的表格,我想把它变成正确的大小写。你们用什么脚本来完成这个?

【问题讨论】:

请记住,在某些情况下,将大写文本正确更改为正确大小写文本可能需要手动更正。以名字为例:我不喜欢拼错我名字的应用程序。 地球上没有任何功能可以让“DAVE DUPLANTIS”正确。大写数据本身就是一个很大的 WTF,因为大多数时候它只是一个表示问题。 我认识一个麦克唐纳,当他被称为麦克唐纳时他会大发雷霆。我也很感谢 O'Keefe 的正确外壳。 @Tomalak:非常正确,这就是为什么您应该接受混合大小写数据并在选择时保留它的原因。完全同意 WTF 部分……特别是如果您接受“国际”字符。 这也是一个文化问题。根据我的经验,英国人和法国人习惯于在有机会的地方将姓氏大写。我只是不明白,它没有增加任何价值。 【参考方案1】:

这个函数:

“正确大小写”所有由空格分隔的“大写”单词 不考虑“小写单词” 即使是非英文字母也能正常工作 是可移植的,因为它不使用最新 SQL Server 版本的花哨功能 可以轻松更改为使用 NCHAR 和 NVARCHAR 来支持 unicode,以及您认为合适的任何参数长度 可以配置空白定义
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

结果:

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

【讨论】:

这绝对是最国际化的解决方案。它有我的投票权。这里唯一的假设是用空格分隔单词。 可能是索引应该从 1 开始?第一个子字符串 (,0,1) 返回 。我正在运行 sqlserver2005 默认情况下,您可能应该将撇号作为空白字符包含在内,这样O'DONNELL 之类的名称就不会更改为O'donnell @Tomalak @i 变量应该从 1 开始,否则输出前会添加一个空格 优秀的小功能。不是 O.P. 要求它,而是如果有人想改变它,使它忽略已经小写的单词,并转换它们,例如"tom bombadil" 改为 "Tom Bombadil",只需将这一行 -- SET @o = @o + @c 改为 SET @o = @o + UPPER(@c) 。 =)【参考方案2】:

这是一个可以解决问题的 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

您仍然需要使用它来更新您的数据。

【讨论】:

这会因为非英语输入而崩溃。 谢谢!首先工作,即使在 Azure SQL Server 上也是如此 :) 我能问一下这进入了什么数据库和表吗? 用 SQL Server 2008 和各种口音试过这个,效果很好。这实际上取决于排序规则 谢谢!它给出了预期的结果。【参考方案3】:
UPDATE titles
  SET title =
      UPPER(LEFT(title, 1)) +
        LOWER(RIGHT(title, LEN(title) - 1))

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

【讨论】:

仅供参考,这适用于单个单词值,但不适用于多个单词值。所以“北卡罗来纳”变成了“北卡罗来纳”,而不是被执行的“北卡罗来纳”。 +1 作为简单的单字解决方案,对我来说效果很好。唯一的 - 如果title 为空,你会得到错误。 @molaro 对空间进行拆分并分别对每个单词进行操作。很好的解决方案,但对可能性的长度有点限制。对于未来的观众,可能希望拆分句子中的第一个单词和第一个单词。 在末尾添加WHERE title IS NOT NULL,解决@Serg的问题。 @Serg 我编辑了代码,因此它不会在使用SUBSTRING 而不是RIGHT 的零长度字符串上运行时出错【参考方案4】:

如果您可以在 SQL Server 中启用 CLR(需要 2005 或更高版本),那么您可以使用 create a CLR function 使用 TextInfo.ToTitleCase built-in function,这将允许您创建一种文化感知方式来执行此操作,只需几行代码。

【讨论】:

我也要在这里投票。它在国际上是安全的,并且使用别人的图书馆,里面可能装满了各种各样的支票。你不能在这里出错:)【参考方案5】:

我知道这是该线程中的后期帖子,但值得一看。这个功能对我有用。所以想分享一下。

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

结果:

【讨论】:

你能描述一下为什么它比 Tomalak 的 ToProperCase 函数 ***.com/questions/230138/… 更好吗? 根据这个答案给出的例子和 Tomalak 的例子,以及 Tomalak 对其作用的描述(“只留下小写单词”),这个答案更好。我没有验证 Tomalak 的,但这个答案确实输入了正确的案例(据我的需要可以验证)。 “正确的大小写是每个单词的第一个字母都大写的任何文本。” - computerhope.com/jargon/p/proper-case.htm【参考方案6】:

我在游戏中有点晚了,但我相信这更实用,它适用于任何语言,包括俄语、德语、泰语、越南语等。 它会使 ' 或 - 或 之后的任何内容变为大写。或(或)或空格(显然是:)。

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

【讨论】:

这很好用,只是“杰克的房子”变成了“杰克的房子” 杰克的房子不是一个人的名字。 O'Brian、O'Connell 是名字 :) 如果您不是专门处理人名,则有必要进行更改。 杰克的房子很容易成为一个企业的名称。【参考方案7】:

这是一个使用序列或数字表而不是循环的版本。您可以修改 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

【讨论】:

【参考方案8】:

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

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

【讨论】:

【参考方案9】:

对@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's 转为 St Elizabeth's o'keefe 转为 O'Keefe o'sullivan 转为 O'Sullivan

其他人认为不同的解决方案更适合非英语输入的情况仍然如此。

【讨论】:

【参考方案10】:

在 Server Server 2016 及更高版本上,您可以使用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

Example

【讨论】:

【参考方案11】:

我在上面发布的链接是解决主要问题的绝佳选择:我们永远无法以编程方式解释所有情况(Smith-Jones、von Haussen、John Smith M.D.),至少不能以优雅的方式。 Tony 引入了异常/中断字符的概念来处理这些情况。 无论如何,基于 Cervo 的想法(上面所有低位字符都以空格开头),替换语句可以包含在基于单个表的替换中。真的,任何低/高字符组合都可以插入@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

【讨论】:

又一个仅限 US-ASCII 的解决方案。 您是否仍将其视为以美国为中心的解决方案,因为它引用了 unicode 字符。我知道原始帖子使用 A-Z ascii 结果集,但解决方案的重点是它是一个表驱动的上部:下部字符配对。替换语句只是引用表。 edit:我更新了示例以使用您的示例输入。感谢您的任何反馈 是否有一种“不优雅”的方式来处理大多数已知的未连字符的名称变体?比如“Mc”、O'C 等等?【参考方案12】:

保持查找异常以处理冯·诺依曼、麦凯恩、德古兹曼和约翰逊-史密斯的情况是有意义的。

【讨论】:

【参考方案13】:

借用并改进了@Richard Sayakanit 的答案。这处理多个单词。就像他的回答一样,这不使用任何 UDF,只使用内置函数(STRING_SPLITSTRING_AGG)而且速度非常快。 STRING_AGG 需要 SQL Server 2017,但您始终可以使用 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

【讨论】:

【参考方案14】:

如果您知道所有数据都只是一个单词,这里有一个解决方案。首先将列更新为all lower,然后运行以下

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

【讨论】:

【参考方案15】:

我想你会发现下面的效率更高:

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 替换为您感兴趣的列,您不会像使用这样发布的 udf 那样为隐式游标付出代价。我发现即使使用我的 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/,但是我们可以使用我们拥有的工具。

注意,您必须使用它,因为您必须将其用作....SELECT dbo.ProperCase(LOWER(column)),因为该列是大写的。它实际上在我的 5,000 个条目(甚至不到一秒)的表格上运行得非常快,即使是较低的条目也是如此。

为了响应关于国际化的 cmet 的狂潮,我提出了以下实现,它处理每个 ascii 字符,仅依赖于 SQL Server 的上层和下层实现。请记住,我们在这里使用的变量是 VARCHAR,这意味着它们只能保存 ASCII 值。为了使用更多的国际字母,您必须使用 NVARCHAR。逻辑类似,但您需要使用 UNICODE 和 NCHAR 代替 ASCII AND 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)

基本上,我的方法的前提是用预先计算换取效率。完整的 ASCII 实现如下:

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

【讨论】:

是的。您的字母表只有 26 个字符。我的有更多。希腊语呢?还是土耳其语? 我认为其他解决方案也是如此。但我已经包含了代码生成器。您可以为您的字母表添加其他部分。您必须将所有内容都设置为 NVARCHAR 并使用 NCHAR 和 UNICODE 进行转换。 我认为你拥有的字符越多,它的效率就越低。但是在某些字符集中,每个符号代表一个完整的单词,所以整个正确的大小写问题不适用...... 我也怀疑有人同时使用每个 unicode 字符。所以可能只是代码为您使用的 2 或 3 个字母生成替换。 这并不意味着您应该使用半生不熟的纯英语解决方案,因为您希望数据“可能在您的字母表中”。就拉丁文字系统而言,(几乎)任何字符都定义了小写/大写。转换函数更多的是关于正确性而不是速度。【参考方案16】:

返回并获取未大写的数据是否为时已晚?

您的客户群中的冯诺依曼、麦凯恩、德古兹曼和约翰逊-史密斯可能不喜欢您处理的结果...

另外,我猜这是为了一次性升级数据?将更正后的名称导出、过滤/修改和重新导入数据库可能更容易,然后您可以使用非 SQL 方法进行名称修复...

【讨论】:

整个命名问题在讨论时作为可能的缺点出现 - 没有迹象表明问题作者引用了包含名称的数据。【参考方案17】:

这是我在 SQLTeam.com 论坛上发现的另一个变体 @ 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

【讨论】:

【参考方案18】:

刚刚了解InitCap()

这里是一些示例代码:

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

【讨论】:

OP 指定 Sql Server,'InitCap()' 是 Oracle 的东西。【参考方案19】:

这在 SSMS 中有效:

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

【讨论】:

【参考方案20】:

最近不得不解决这个问题,并在没有什么事情完全符合我想要的一切之后想出了以下内容。这将做一个完整的句子,特殊单词处理的案例。我们还遇到了许多简单方法处理的单字符“单词”问题,但更复杂的方法却没有。单个返回变量,也没有循环或游标。

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

【讨论】:

【参考方案21】:

将您的数据复制并粘贴到 MS Word 中,并使用内置的文本转换来“大写每个单词”。与您的原始数据进行比较以解决异常。看不到任何手动回避“MacDonald”和“IBM”类型异常的方法,但这就是我完成 FWIW 的方式。

【讨论】:

【参考方案22】:

遗憾的是,我提出了另一个功能。这个似乎比大多数更快,但只大写由空格分隔的单词的第一个字母。我已经检查过输入不为空,并且如果在字符串中间的某个位置有多个空格,它就可以工作。我正在交叉应用长度函数,所以我不必调用它两次。我原以为 SQL Server 会缓存该值。警告购买者。

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

【讨论】:

【参考方案23】:

这个功能对我有用

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

【讨论】:

【参考方案24】:

我知道魔鬼在细节中(尤其是在涉及人们的个人数据的地方),并且拥有适当大写的名字会非常好,但上述麻烦是为什么我们当中务实、注重时间的人使用以下内容:

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

根据我的经验,人们很高兴看到他们的名字……即使是在句子进行到一半的时候。

参考:俄罗斯人用铅笔!

【讨论】:

否认这个问题是没有帮助的。这个“答案”是最好的评论。

以上是关于SQL Server:将所有大写字母变为正确大小写/标题大小写的主要内容,如果未能解决你的问题,请参考以下文章

PCB MS SQL SERVER 字段含小写字母更新为大写字母

将所有小写字母大写的程序不起作用

字符串

用破折号替换空格并使所有字母变为小写

python笔记

sql server数据库表中各字段名需要大写吗