【问题标题】:SQL Proper Case Function Query RefinementSQL适当案例函数查询细化
【发布时间】:2014-05-20 08:34:09
【问题描述】:

我有一个名称表,我正在尝试将其从大写转换为正确大小写。下面的代码几乎完全符合我的要求。当我测试它时,我注意到有些人的名字中有罗马数字,Mc* 和 O'* 在表中。自然地,该查询将任何多个罗马数字转换为 Iv,就像它应该做的那样,任何 MCDONALDS 或 O'DANIEL 都被转换为 Mcdonalds 和 O'daniel。我试图弄清楚如何对这个函数进行彻底的更改,以便我可以运行我的更新查询,但我仍然在下班时间将我的 SQL 知识和平磨合在一起。任何帮助/建议将不胜感激。我进行了谷歌搜索并找到了几个示例,但我尝试过的那些都不起作用。我必须做的更正量相对较小(1000 行表中的 17 次更正),但我想尝试整理它以尽可能减少人为错误。

提前感谢您的帮助。

CREATE FUNCTION [dbo].[f_ProperCase]
(@Text as varchar(80))
RETURNS varchar(80) as
BEGIN

DECLARE @Reset bit
DECLARE @Ret varchar(80)
DECLARE @i int
DECLARE @c char(1)

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 
CASE WHEN SUBSTRING(@Text,@i-4,5) like '_[a-z] [DOL]''' THEN 1 
WHEN SUBSTRING(@Text,@i-4,5) like '_[a-z] [D][I]' THEN 1 
WHEN SUBSTRING(@Text,@i-4,5) like '_[a-z] [M][C]' THEN 1 
WHEN SUBSTRING(@Text,@i-4,5) like '_[a-z] [M][c][*]' THEN 1 --Convert MCDONALD to     McDonald
WHEN SUBSTRING(@Text,@I-4,5) like '_[a-z] [O][''][*]' THEN 1 --Convert O'DONNEL to O'Donnel
ELSE 0 
END = 1 
THEN 1 
ELSE CASE WHEN @c like '[a-zA-Z]' or @c in ('''') THEN 0 
ELSE 1 
END 
END,
@i = @i +1
RETURN @Ret
end

【问题讨论】:

    标签: sql function


    【解决方案1】:

    我调整了一些以处理名称中包含的后缀。这几乎处理了我扔给它的任何东西。我们有时在一些后缀之后有连字符的名称和句点。我知道从 I-IX 处理是多余的,但很容易将 X 添加到 V 检查。

    ALTER FUNCTION dbo.udf_ProperCase
    (@Text as varchar(1024))
    RETURNS varchar(1024) 
    AS
    /* 
    Created to ProperCase most common LastName (Mc/Mac/O'/D'/L') and handle I(first)-IX(nineteenth) suffixes
    
    Original Code: https://stackoverflow.com/questions/22923616/sql-proper-case-function-query-refinement
    SELECT dbo.udf_ProperCase('iitest demetrii mcdonald o''neil victor second 2nd ii iii iv v vi vii viii ix x xi test')
    */
    BEGIN
        DECLARE @Reset bit
        DECLARE @Ret varchar(1024)
        DECLARE @i int
        DECLARE @c char(1)
        DECLARE @Text1 varchar(1025)
    
        SELECT @Reset = 1, @i=1, @Ret = '', @Text1 = ' ' + @Text + '  '  --Ensure one space before to make first char upper and after to handle suffixes
        --Loop through each character, comparing prior/next to determine if need to handle
        WHILE @i <= LEN(@Text1)
          BEGIN
            SELECT 
                 @c= SUBSTRING(@Text1,@i,1)
                ,@Ret = @Ret + CASE WHEN @Reset=1 THEN UPPER(@c) ELSE LOWER(@c) END
                ,@Reset= CASE 
                            WHEN 
                                CASE 
                                    WHEN SUBSTRING(@Text1,@i-2,3) like '[ -][DdOoLl][''`]' THEN 1   --Names (including hyphenated) beginning with D/O/L                             
                                    WHEN SUBSTRING(@Text1,@i-2,4) like ' [Mm][cC][a-zA-Z]' THEN 1  --Names with Mc
                                    WHEN SUBSTRING(@Text1,@i-3,5) like ' [Mm][Aa][cC][a-zA-Z]' THEN 1  --Names with Mac
                                    WHEN SUBSTRING(@Text1,@i-1,4) like ' [Ii][Ii][ .]' THEN 1  --Handle II (include ending with Space or period)
                                    WHEN SUBSTRING(@Text1,@i-1,5) like ' [Ii][Ii][Ii][ .]' THEN 1  --Handle III
                                    WHEN SUBSTRING(@Text1,@i-2,4) like ' [Ii][Ii][ .]' THEN 1  --Handle II
                                    WHEN SUBSTRING(@Text1,@i-2,5) like ' [Ii][Ii][Ii][ .]' THEN 1  --Handle III
                                    WHEN SUBSTRING(@Text1,@i-3,4) like ' [Ii][Ii][ .]' THEN 1  --Handle II
                                    WHEN SUBSTRING(@Text1,@i-3,5) like ' [Ii][Ii][Ii][ .]' THEN 1  --Handle III
                                    
                                    WHEN SUBSTRING(@Text1,@i-1,4) like ' [Ii][VvXx][ .]' THEN 1 --Handle IV
    
                                    WHEN SUBSTRING(@Text1,@i-1,4) like ' [VvXx][Ii][ .]' THEN 1  --Handle VI
                                    WHEN SUBSTRING(@Text1,@i-1,5) like ' [VvXx][Ii][Ii][ .]' THEN 1  --Handle VII
                                    WHEN SUBSTRING(@Text1,@i-1,6) like ' [VvXx][Ii][Ii][Ii][ .]' THEN 1  --Handle VIII
                                    WHEN SUBSTRING(@Text1,@i-2,4) like ' [VvXx][Ii][ .]' THEN 1  --Handle VI
                                    WHEN SUBSTRING(@Text1,@i-2,5) like ' [VvXx][Ii][Ii][ .]' THEN 1  --Handle VII
                                    WHEN SUBSTRING(@Text1,@i-2,6) like ' [VvXx][Ii][Ii][Ii][ .]' THEN 1  --Handle VIII
                                    WHEN SUBSTRING(@Text1,@i-3,4) like ' [VvXx][Ii][ .]' THEN 1  --Handle VI
                                    WHEN SUBSTRING(@Text1,@i-3,5) like ' [VvXx][Ii][Ii][ .]' THEN 1  --Handle VII
                                    WHEN SUBSTRING(@Text1,@i-3,6) like ' [VvXx][Ii][Ii][Ii][ .]' THEN 1  --Handle VIII
                                    ELSE 0 
                                END = 1 THEN 1 
                            ELSE 
                                CASE 
                                    WHEN @c like '[a-zA-Z`]' or @c in ('''') or @c like '[0-9]' THEN 0  --If any letter, single-quote or number, then keep next lowercase
                                    ELSE 1  --Anything else (e.g. Space dash, And(&), etc. make next Upper-Case)
                                END 
                          END
                ,@i = @i +1 
          END   
        
        RETURN stuff(@Ret, 1, 1, '')
    END
    
    GO
    

    【讨论】:

      【解决方案2】:

      我会做不同的事情:

      CREATE FUNCTION [dbo].[f_ProperCase]
      (@Text as varchar(80))
      RETURNS varchar(80) as
      BEGIN
      
      DECLARE @Reset bit
      DECLARE @Ret varchar(80)
      DECLARE @i int
      DECLARE @c char(1)
      DECLARE @Text1 varchar(81)
      
      SELECT @Reset = 1, @i=1, @Ret = '', @Text1 = ' ' + @Text
      
      WHILE @i <= LEN(@Text1)
          SELECT @c= SUBSTRING(@Text1,@i,1),
          @Ret = @Ret + CASE WHEN @Reset=1 THEN UPPER(@c) ELSE LOWER(@c) END,
          @Reset= CASE WHEN 
          CASE WHEN SUBSTRING(@Text1,@i-2,3) like ' [DdOoLl]''' THEN 1 
          WHEN SUBSTRING(@Text1,@i-2,4) like ' [Mm][cC][a-zA-Z]' THEN 1 
          WHEN SUBSTRING(@Text1,@i-3,5) like ' [Mm][Aa][cC][a-zA-Z]' THEN 1 
          ELSE 0 
          END = 1 
          THEN 1 
          ELSE CASE WHEN @c like '[a-zA-Z]' or @c in ('''') THEN 0 
          ELSE 1 
          END 
          END,
          @i = @i +1
      RETURN stuff(@Ret, 1, 1, '')
      end
      

      此功能支持O'、L'、D',以及Mc、Mac。该函数还可以从任何大小写(不仅是大写)转换为正确的大小写

      SQL Fiddle

      select dbo.f_ProperCase('CORMACK')
            ,dbo.f_ProperCase('Mcdonald ronald')
            ,dbo.f_ProperCase('o''hara')
      
      |         |                 |        |
      |---------|-----------------|--------|
      | Cormack | McDonald Ronald | O'Hara |
      

      【讨论】:

      • 我只是在我的测试系统中厌倦了这个,它就像一个魅力。非常感谢你的帮助,Cha。
      • 效果很好,唯一的问题是对于像“CORMACK”这样的名称,它将返回“CormacK”
      • 太棒了,感谢您花时间更新,完美运行
      • 有人在 MySQL 中有这个工作吗?我的函数语法很弱,似乎无法让它工作。
      猜你喜欢
      • 2014-07-12
      • 2014-11-08
      • 2018-12-09
      • 1970-01-01
      • 2014-11-10
      • 2020-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多