【问题标题】:Built-in function to capitalise the first letter of each word内置函数将每个单词的首字母大写
【发布时间】:2011-07-07 01:23:53
【问题描述】:

如果 SQL Server 中已经存在这样的函数,我不想为此创建自定义函数。

输入字符串:This is my string to convert
预期输出:This Is My String To Convert

【问题讨论】:

  • 从技术上讲,这将是 PascalCase。
  • @thomas,从技术上讲,两者都不是,它只是一串大写的单词
  • @nathan gonzalez - 我的立场是正确的。

标签: sql sql-server-2008 pascalcasing


【解决方案1】:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[InitCap] ( @InputString varchar(4000) ) 
RETURNS VARCHAR(4000)
AS
BEGIN

DECLARE @Index          INT
DECLARE @Char           CHAR(1)
DECLARE @PrevChar       CHAR(1)
DECLARE @OutputString   VARCHAR(4000)

SET @OutputString = LOWER(@InputString)
SET @Index = 1

WHILE @Index <= LEN(@InputString)
BEGIN
    SET @Char     = SUBSTRING(@InputString, @Index, 1)
    SET @PrevChar = CASE WHEN @Index = 1 THEN ' '
                         ELSE SUBSTRING(@InputString, @Index - 1, 1)
                    END

    IF @PrevChar IN (' ', ';', ':', '!', '?', ',', '.', '_', '-', '/', '&', '''', '(')
        SET @OutputString = STUFF(@OutputString, @Index, 1, UPPER(@Char))

    SET @Index = @Index + 1
END

RETURN @OutputString

END



Declare @str nvarchar(100)
SET @str = 'my string to convert'
SELECT @str = [dbo].[InitCap](@str)
SELECT @str 

【讨论】:

    【解决方案2】:

    AFAIK,SQL Server 对此没有内置函数。
    您必须为它编写自定义函数。

    试试这个。

    CREATE FUNCTION [dbo].[CamelCase]
    (@Str varchar(8000))
    RETURNS varchar(8000) AS
    BEGIN
      DECLARE @Result varchar(2000)
      SET @Str = LOWER(@Str) + ' '
      SET @Result = ''
      WHILE 1=1
      BEGIN
        IF PATINDEX('% %',@Str) = 0 BREAK
        SET @Result = @Result + UPPER(Left(@Str,1))+
        SubString  (@Str,2,CharIndex(' ',@Str)-1)
        SET @Str = SubString(@Str,
          CharIndex(' ',@Str)+1,Len(@Str))
      END
      SET @Result = Left(@Result,Len(@Result))
      RETURN @Result
    END  
    

    输出:

    Input String    : 'microSoft sql server'
    Output String   : 'Microsoft Sql Server'
    

    【讨论】:

    • 很好,但只处理空格作为分隔符。例如,不会处理破折号/连字符,但仍会回答问题。也不会处理 NULL,而是返回一个空字符串。
    • 也不处理单字母字符串(即First Middle Last names 作为单独的字符串):dbo.CamelCase(p.FirstName), dbo.CamelCase(p.LastName), dbo.CamelCase(p .MiddleName)
    【解决方案3】:

    我不得不选择“不,那不存在”。这是基于多年来对 T-SQL 中可用字符串函数的细读以及 SQL Server 2008 R2 中一些最近的 5 天课程。

    当然,我仍然可能是错的:)。

    【讨论】:

      【解决方案4】:

      如果您的操作目标是美化名称字符串,则可以将正确的大写定义为由非字母字符分隔的每个单词的首字母。

      其他方案不考虑:

      1. 保留间距(尤其是尾随空格)。
      2. 保留 NULL、空字符串或仅包含空格的字符串。
      3. 处理的不仅仅是空格(例如破折号、逗号、下划线等...)
      4. 在单词/标记之间处理多个非字母字符。
      5. 处理异常(例如,“詹姆斯威廉”中的 McDonald 或 III 底牙 III")。

      注意:我的解决方案不处理异常。
      如果您非常关心这些,那么我建议为这些编写一个 CLR C# 程序集,因为它会很棘手,而字符串是 C# 擅长的领域。
      这里的另一个解决方案试图解决这个问题,但它仍然需要“ivan wrong the iv”并输出“**IV***an Terrible The IV*”。

      这是我想出的功能:

      IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fs_PascalCase]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
      DROP FUNCTION [dbo].[fs_PascalCase]
      GO
      SET ANSI_NULLS ON
      GO
      SET QUOTED_IDENTIFIER ON
      GO
      CREATE FUNCTION [dbo].[fs_PascalCase]
      (
          @Text nVarChar(MAX)
      )
      RETURNS nVarChar(MAX)
      AS
      BEGIN
              SET @Text = LOWER(@Text)--This step is optional.  Keep if you want the code below to control all casing. - 11/26/2013 - MCR.
          DECLARE @New nVarChar(MAX) = (CASE WHEN @Text IS NULL THEN NULL ELSE '' END)--Still return null when source is null. - 11/26/2013 - MCR.
          DECLARE @Len   Int = LEN(REPLACE(@Text, ' ', '_'))--If you want to count/keep trailing-spaces, you MUST use this!!! - 11/26/2013 - MCR.
          DECLARE @Index Int = 1--Sql-Server is 1-based, not 0-based.
          WHILE (@Index <= @Len)
              IF (SUBSTRING(@Text, @Index, 1) LIKE '[^a-z]' AND @Index + 1 <= @Len)--If not alpha and there are more character(s).
                  SELECT @New = @New + UPPER(SUBSTRING(@Text, @Index, 2)), @Index = @Index + 2
              ELSE
                  SELECT @New = @New +       SUBSTRING(@Text, @Index, 1) , @Index = @Index + 1
      
          --If @Text is null, then @Len will be Null, and everything will be null.
          --If @Text is '',   then (@Len - 1) will be -1, so ABS() it to use 1 instead, which will still return ''.
          RETURN ( UPPER(LEFT(@New, 1)) + RIGHT(@New, ABS(@Len - 1)) )
      END
      GO
      


      你可以这样称呼它:

      SELECT dbo.fs_PascalCase(NULL)[Null],
             dbo.fs_PascalCase('')[EmptyString],
             dbo.fs_PascalCase('hello   how are-you TODAY    ')[LongString]
      


      输出将如下所示:

      【讨论】:

        【解决方案5】:

        我的策略

        • 如果名称已经混合大小写,请相信它是正确的。
        • 如果名称不是大小写混合,则执行以下操作:
        • 修剪名称以消除空格
        • 记下以“Mc”开头的名称,例如“McDavid”
        • 考虑像 O'Reilly 这样带有撇号的名字
        • “Anderson-Johnson”连字符名称(已婚名称)的帐户
        • 考虑多个单词名称,例如“La Russa”
        • 确保名称字段中包含的后缀正确大写

        守则

        这是我的原始帖子:Converting String to Camel Case in SQL Server

        CREATE FUNCTION [dbo].[GetCamelCaseName]
        (
            @Name varchar(50)
        )
        RETURNS VARCHAR(50) WITH SCHEMABINDING
        AS
        BEGIN
            -- Declare the return variable here
            DECLARE @NameCamelCase VARCHAR(50)  
        
            -- This is determining whether or not the name is in camel case already (if the 1st character is uppercase
            -- and the third is lower (because the 2nd could be an apostrophe).  To do this, you have to cast the 
            -- character as varbinary and compare it with the upper case of the character cast as varbinary.  
        
            IF (CAST(SUBSTRING(@Name, 1,1) as varbinary) = CAST(SUBSTRING(UPPER(@Name), 1, 1) as varbinary)         
                    AND ((CAST(SUBSTRING(@Name, 2,1) as varbinary) = CAST(SUBSTRING(LOWER(@Name), 2, 1) as varbinary)
                            AND SUBSTRING(@Name, 2,1) != '''')
                        or
                        (CAST(SUBSTRING(@Name, 4,1) as varbinary) = CAST(SUBSTRING(LOWER(@Name), 4, 1) as varbinary)
                            AND SUBSTRING(@Name, 2,1) = '''')))
        
                BEGIN
                    SELECT @NameCamelCase = RTRIM(LTRIM(@Name))
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' sr', ' Sr')           
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' jr', ' Jr')       
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' ii', ' II')   
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' iii', ' III')
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' DE ', ' de ')
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, 'macdonald', 'MacDonald')
        
                    if (@NameCamelCase LIKE '% iv') -- avoid changing "Ivan" to "IVan"
                        SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' iv', ' IV')
        
                    if ((@NameCamelCase = 'i') or (@NameCamelCase = 'ii') or (@NameCamelCase = 'iii') or (@NameCamelCase = 'iv'))
                        SELECT @NameCamelCase = UPPER(@NameCamelCase)
        
                    RETURN @NameCamelCase       
        
                END
        
            ELSE
        
                BEGIN       
        
                    SELECT @NameCamelCase = RTRIM(LTRIM(@Name))
        
                    -- "Mc-"
                    SELECT @NameCamelCase = 
                        CASE 
                            WHEN @Name LIKE 'mc%'
                                THEN UPPER(SUBSTRING(@Name, 1, 1)) + LOWER(SUBSTRING(@Name, 2, 1)) + UPPER(SUBSTRING(@Name, 3, 1))  + LOWER(SUBSTRING(@Name, 4, 47))
                            ELSE
                               UPPER(SUBSTRING(@Name, 1, 1)) + LOWER(SUBSTRING(@Name, 2, 49))
                        END
        
                    -- Apostrophes
                    SELECT @NameCamelCase = 
                        CASE 
                            WHEN @NameCamelCase LIKE '%''%'
                                THEN SUBSTRING(@NameCamelCase, 1, CHARINDEX('''', @NameCamelCase) - 1) + ''''  + UPPER(SUBSTRING(@NameCamelCase, CHARINDEX('''', @NameCamelCase) + 1, 1)) + SUBSTRING(@NameCamelCase, CHARINDEX('''', @NameCamelCase) + 2, 50)
                            ELSE
                                @NameCamelCase
                        END 
        
        
                    -- Hyphenated names (do it twice to account for double hyphens)
                    SELECT @NameCamelCase = 
                        CASE 
                            WHEN @NameCamelCase LIKE '%-%'
                                THEN SUBSTRING(@NameCamelCase, 1, CHARINDEX('-', @NameCamelCase) - 1) + '^'  + UPPER(SUBSTRING(@NameCamelCase, CHARINDEX('-', @NameCamelCase) + 1, 1)) + SUBSTRING(@NameCamelCase, CHARINDEX('-', @NameCamelCase) + 2, 50)
                            ELSE
                                @NameCamelCase
                        END 
        
                    SELECT @NameCamelCase = 
                        CASE 
                            WHEN @NameCamelCase LIKE '%-%'
                                THEN SUBSTRING(@NameCamelCase, 1, CHARINDEX('-', @NameCamelCase) - 1) + '^'  + UPPER(SUBSTRING(@NameCamelCase, CHARINDEX('-', @NameCamelCase) + 1, 1)) + SUBSTRING(@NameCamelCase, CHARINDEX('-', @NameCamelCase) + 2, 50)
                            ELSE
                                @NameCamelCase
                        END 
        
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, '^', '-')
        
                    -- Multiple word names (do it twice to account for three word names)
                    SELECT @NameCamelCase = 
                        CASE 
                            WHEN @NameCamelCase LIKE '% %'
                                THEN SUBSTRING(@NameCamelCase, 1, CHARINDEX(' ', @NameCamelCase) - 1) + '?'  + UPPER(SUBSTRING(@NameCamelCase, CHARINDEX(' ', @NameCamelCase) + 1, 1)) + SUBSTRING(@NameCamelCase, CHARINDEX(' ', @NameCamelCase) + 2, 50)
                            ELSE
                                @NameCamelCase
                        END 
        
                    SELECT @NameCamelCase = 
                        CASE 
                            WHEN @NameCamelCase LIKE '% %'
                                THEN SUBSTRING(@NameCamelCase, 1, CHARINDEX(' ', @NameCamelCase) - 1) + '?'  + UPPER(SUBSTRING(@NameCamelCase, CHARINDEX(' ', @NameCamelCase) + 1, 1)) + SUBSTRING(@NameCamelCase, CHARINDEX(' ', @NameCamelCase) + 2, 50)
                            ELSE
                                @NameCamelCase
                        END 
        
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, '?', ' ')
        
                    -- Names in Parentheses         
                    SELECT @NameCamelCase = 
                        CASE 
                            WHEN @NameCamelCase LIKE '%(%'
                                THEN SUBSTRING(@NameCamelCase, 1, CHARINDEX('(', @NameCamelCase) - 1) + '('  + UPPER(SUBSTRING(@NameCamelCase, CHARINDEX('(', @NameCamelCase) + 1, 1)) + SUBSTRING(@NameCamelCase, CHARINDEX('(', @NameCamelCase) + 2, 50)
                            ELSE
                                @NameCamelCase
                        END 
        
        
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' sr', ' Sr')           
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' jr', ' Jr')           
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' ii', ' II')
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' iii', ' III')
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' DE ', ' de ')
                    SELECT @NameCamelCase = REPLACE(@NameCamelCase, 'macdonald', 'MacDonald')
        
                    if (@NameCamelCase LIKE '% iv')
                        SELECT @NameCamelCase = REPLACE(@NameCamelCase, ' iv', ' IV')
        
                    if ((@NameCamelCase = 'i') or (@NameCamelCase = 'ii') or (@NameCamelCase = 'iii') or (@NameCamelCase = 'iv'))
                        SELECT @NameCamelCase = UPPER(@NameCamelCase)
        
                    -- Return the result of the function
                    RETURN ISNULL(@NameCamelCase, '')
        
                END
        
            RETURN ISNULL(@NameCamelCase, '')
        
        END
        

        【讨论】:

        • 我喜欢你用这个去哪里。但是,此代码在 SQL Server 2008 R2 下没有为我执行。错误是“必须声明标量变量“@NameCamelCase”。”。
        • 谢谢。我试图让它更简单一些,但错过了一些东西。正在更新中...
        • 对此投了赞成票:“如果名称已经混合大小写,请相信它是正确的。”
        【解决方案6】:

        使用 SQL 2017,函数可能如下所示:

        create function dbo.cap_words (@str varchar(max))
        returns varchar(max)
        as
        begin
            declare @result varchar(max);
            select @result = string_agg( upper(left(value,1)) + substring(value,2,999),' ') from string_split(lower(@str),' ') 
            return @result;
        end
        

        【讨论】:

          【解决方案7】:

          和我一样,很多人可能正在寻找查询内解决方案,查询创建功能,我想出了一个不同的方法:

          SELECT REPLACE(
              STUFF( 
                  (SELECT' '+ LTRIM(RTRIM(UPPER(SUBSTRING(value, 1,1))+LOWER(SUBSTRING(value, 2, LEN(value)))))
                   FROM STRING_SPLIT([Message], ' ')
                   FOR XML PATH('')
                   ), 1, 1, ''
             ), ''/*Control delimiters here*/, '') FROM [dbo].[MessageQueue]
          

          为您自己的表更改 [MessageQueue] 表,为您的字段更改 [Message]。

          函数 STRING_SPLIT 可能需要将您的 SQL 兼容性级别提高到 130。

          使用外部 REPLACE 函数来设置任何你想要的分隔符。

          【讨论】:

            【解决方案8】:

            这里是简单的事情,不要把它复杂化。

            甲骨文: SELECT initcap(lower('This is MY string to conVerT')) FROM dual;

            【讨论】:

            • 问题是关于 sqlserver 而不是 oracle。
            • 你可以删除你的答案以避免得到负分
            猜你喜欢
            • 2016-05-01
            • 2015-11-10
            • 2020-08-30
            • 2015-11-04
            • 2012-11-11
            • 2012-07-24
            • 2019-08-25
            • 2016-12-05
            • 2016-01-10
            相关资源
            最近更新 更多