【问题标题】:Making first letter of every word upper case with a condition使用条件将每个单词的首字母大写
【发布时间】:2016-03-23 13:59:50
【问题描述】:

我有一个类似于VENDOR CORPORATION (GA/ATL) 的文本。我想让它看起来像Vendor Corporation (GA/ATL)

所以,除了() 之间存在的单词之外,我只想将每个单词的第一个字母大写。

我遇到了 - UPPER(LEFT(FIELD_NAME,1))+LOWER(SUBSTRING(FIELD_NAME,2,LEN(FIELD_NAME))),但它一次只能处理一个单词,并且没有我想要的功能。最需要一个可以完成这项工作的功能。

【问题讨论】:

  • 我认为你需要为这个非常特殊的目的编写一个用户定义的函数。
  • 从触发器调用,以确保存储的数据始终具有正确的格式。
  • 这个函数叫做InitCap。你需要调整一个像这个答案stackoverflow.com/a/11688803/21336handle parens 中的解决方案

标签: sql sql-server sql-server-2008-r2


【解决方案1】:

尝试像这样使用function

BEGIN

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

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 (' ', ';', ':', '!', '?', ',', '.', '_', '-', '/', '&', '''', '(')
    BEGIN
        IF  @PrevChar != '(' AND @PrevChar != '/'
            SET @OutputString = STUFF(@OutputString, @Index, 1, UPPER(@Char))
        IF  @PrevChar = '(' 
            SET @OutputString = LEFT(@OutputString, LEN(@OutputString) - LEN(SUBSTRING(@OutputString, CHARINDEX('(',@OutputString), CHARINDEX(')',@OutputString)))) +  UPPER(SUBSTRING(@OutputString, CHARINDEX('(',@OutputString), CHARINDEX(')',@OutputString)))
    END

    SET @Index = @Index + 1
END

RETURN @OutputString

END

用法

SELECT [dbo].[InitCap]('VENDOR CORPORATION (GA/ATL)')

输出

Vendor Corporation (GA/ATL)

【讨论】:

  • 需要更多的工作来处理except those words which exists between ( and )
  • 只是提个醒.. 在我意识到() 之后的文字没有得到正确处理后,我不得不编辑我的答案。你的函数也会把'VENDOR CORPORATION (GA/ATL) duhh duhh'变成'Vendor Corporation (GA/ATL) DUHH DUHH'不确定这是否是个问题
  • @JamieD77 这不是问题,因为我的字符串在) 之后没有任何文本,但很聪明!
【解决方案2】:

作为上述答案的替代方案。如果您只想忽略() 之间的内容,您可以使用InitCap 函数的略微修改版本

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(255)
        SET @OutputString = LOWER(@InputString)
        SET @Index = 1
        WHILE @Index <= LEN(@InputString) 
            BEGIN
                SET @Char = SUBSTRING(@InputString,@Index,1)
                IF @Char = '(' 
                    BEGIN
                        WHILE @Index <= LEN(@InputString)
                            AND @Char NOT IN (')') 
                            BEGIN 
                                SET @Index = @Index + 1
                                SET @PrevChar = @Char
                                SET @Char = SUBSTRING(@InputString,@Index,1)
                                SET @OutputString = STUFF(@OutputString,@Index,1,@Char)
                            END
                    END              
                IF @PrevChar IN (' ',';',':','!','?',',','.','_','-','/','&','''') 
                    BEGIN
                        IF @PrevChar != ''''
                            OR UPPER(@Char) != 'S' 
                            SET @OutputString = STUFF(@OutputString,@Index,1,UPPER(@Char))
                    END
                SET @Index = @Index + 1
                SET @PrevChar = @Char
            END
        RETURN @OutputString
    END
GO

示例

SELECT  [dbo].[InitCap](n)
FROM    ( VALUES ( 'VENDOR CORPORATION (GA/ATL)'), 
                 ( 'VENDOR CORPORATION (ga/atl)'), 
                 ( 'VENDOR CORPORATION (Ga/Atl)') ) t (n)

output
--------
Vendor Corporation (GA/ATL)
Vendor Corporation (ga/atl)
Vendor Corporation (Ga/Atl)

如果您总是想在 () 中使用大写字母,只需在这两个地方使用 SET @OutputString = STUFF(@OutputString,@Index,1,UPPER(@Char))

【讨论】:

  • 你让它看起来很简单。很好的答案。
【解决方案3】:

使用 Jeff Moden 分离器(可在此处找到。http://www.sqlservercentral.com/articles/Tally+Table/72993/)可以完成此操作。然后,您需要使用交叉表(也称为条件聚合)将片段重新组合在一起。您也可以使用 PIVOT 执行此操作,但我发现交叉表的语法不那么钝,并且已被证明在性能方面稍快一​​些。这也使用了此处的 InitCap 函数。 How to update data as upper case first letter with t-sql command?

declare @Value varchar(100) = 'VENDOR CORPORATION (GA/ATL)';

with sortedValues as
(
    select Case when left(s.Item, 1) = '(' then s.Item else dbo.InitCap(s.Item) end as CorrectedVal
        , s.ItemNumber
    from dbo.DelimitedSplit8K(@Value, ' ') s
)

select MAX(case when ItemNumber = 1 then CorrectedVal end) + ' '
     + MAX(case when ItemNumber = 2 then CorrectedVal end) + ' '
     + MAX(case when ItemNumber = 3 then CorrectedVal end)
from sortedValues

如果您不提前知道您将拥有多少“单词”,您可以将此交叉表调整为动态版本。您可以在此处阅读有关动态交叉表的更多信息。 http://www.sqlservercentral.com/articles/Crosstab/65048/

--编辑--

感谢 JamieD77 提出使用 STUFF 的建议。我特别喜欢这个选项,因为我有另一个使用计数表的 InitCap 版本,而不是这里引用的使用 while 循环的版本。使用 STUFF 有助于将整个事情变成内联表值函数,因此它会非常快。如果有人想在不循环的情况下查看 InitCap,请告诉我,我很乐意发布。

这是使用建议的 STUFF 方法的查询。

SELECT STUFF((SELECT   ' ' + s.CorrectedVal
    FROM sortedValues s
    ORDER BY s.ItemNumber
    FOR
    XML PATH('')
    ),1,1,'')

【讨论】:

  • @JamieD77 我非常喜欢 STUFF 选项。我有另一个不使用循环的 InitCap 函数,它是基于计数表的,所以像这样使用 STUFF 将保持一切都没有任何循环。我会更新我的答案。
猜你喜欢
  • 2015-11-10
  • 2014-11-15
  • 1970-01-01
  • 2020-08-30
  • 2015-11-04
  • 2012-11-11
  • 2012-07-24
  • 1970-01-01
  • 2016-12-05
相关资源
最近更新 更多