SQL

时间:2017-04-11 16:43:30

标签: sql sql-server tsql

我根据系统设置格式化名称。可用的设置值为

  • 最后,Prefix First,Middle,Suffix
  • Last,First,Middle,Suffix
  • Last,Prefix First,Suffix
  • 最后,第一,后缀
  • First Middle Last Suffix
  • First Middle Last
  • 第一个最后的后缀
  • First Last
  • Prefix First Middle Last
  • Prefix First Middle Last Suffix
  • Prefix First Last
  • Prefix First Last Suffix

我在没有使用开关盒的情况下想出了以下内容。

    DECLARE @fullname NVARCHAR(225),
            @LastName NVARCHAR(50),
            @FirstName NVARCHAR(50),
            @MiddleName NVARCHAR(50),
            @Prefix NVARCHAR(32),
            @Suffix NVARCHAR(32)

    SET @fullname = 'Last, Prefix First, Middle, Suffix' -- this would be pulled from db

    SELECT @LastName = 'Last',  @FirstName= 'First', @MiddleName= 'M', @Prefix= 'Mr.', @Suffix = 'MD' -- this would be pulled from db

    SET @fullname = REPLACE(@fullname, N'Last', COALESCE((' ' + @LastName), ' [NA]'));
    SET @fullname = REPLACE(@fullname, N'First', COALESCE((' ' + @FirstName), ' [NA]'));
    SET @fullname = REPLACE(@fullname, N'Middle', COALESCE((' ' + @MiddleName), ''));
    SET @fullname = REPLACE(@fullname, N'Prefix', COALESCE((' ' + @Prefix), ''));
    SET @fullname = LTRIM(RTRIM(REPLACE(@fullname, N'Suffix', COALESCE((' ' + @Suffix), ''))));

    WHILE RIGHT(@fullname, 1)=','
    BEGIN
        SELECT @fullname=RTRIM(SUBSTRING(@fullname, 1, LEN(@fullname)-1))
    END

    SELECT @fullname

MiddleName,Prefix和Suffix是可以为空的字段。 有没有更好的方法来做到这一点?

2 个答案:

答案 0 :(得分:0)

我不明白你为什么要使用额外的空间。您已经拥有模式中的空格:

SET @fullname = REPLACE(@fullname, N'Last', COALESCE(@LastName, ' [NA]'));
SET @fullname = REPLACE(@fullname, N'First', COALESCE(@FirstName, ' [NA]'));
SET @fullname = REPLACE(@fullname, N'Middle', COALESCE(@MiddleName, ''));
SET @fullname = REPLACE(@fullname, N'Prefix', COALESCE(@Prefix, ''));

然后不需要修剪。如果你担心像凯特米德尔顿这样的名字"干扰,然后我建议将模式设置为:

SET @fullname = '[Last], [Prefix] [First], [Middle], [Suffix]' ;

如果您无法在数据库中对其进行格式化,请在使用之前对其进行格式化:

SET @fullname = REPLACE(@fullname, 'Last', '[Last]');
. . .

这将防止名称元素和真实姓名之间的冲突。

答案 1 :(得分:0)

如果您对UDF持开放态度,这里有一个显着修改过的函数,可用于对所有记录或字符串进行“标记”。

令牌将是,例如[[First_Name]]

现在,任何剩余的[[TOKENS]]或额外/重复空间都将被移除(感谢戈登的精彩技巧)

只需注意一点:字段名称必须与令牌匹配(反之亦然)/

参数是:

  1. 行数据为XML Raw - 可以像(Select A.* for XML Raw)
  2. 一样简单
  3. 所需模式 - [[Last_Name]], [[First_Name]] [[Middle]]
  4. 缺失值的默认值 - [NA]或任何字符串
  5. 表现令人尊敬。例如,1.424秒内的10,000条记录

    示例或dbFiddle

    Declare @YourTable table (ID int,[First] varchar(50),[Last] varchar(50),[Middle] varchar(25),[Suffix] varchar(50))
    Insert into @YourTable values
    (1,'John','Smith','James','Jr.'),
    (2,'Jane','Doe','',null)
    
    Declare @Pattern varchar(max) = '[[Last]], [[First]] [[Middle]] [[Suffix]]'
    
    Select A.ID
          ,Formatted = [dbo].[udf-Str-Tokenize](B.XMLData,@Pattern,'[NA]')
     From  @YourTable A
     Cross Apply (values ((Select A.* for XML Raw)) ) B(XMLData)
    

    <强>返回

    ID  Formatted
    1   Smith, John James Jr.
    2   Doe, Jane [NA]
    

    感兴趣的UDF

    CREATE FUNCTION [dbo].[udf-Str-Tokenize](@XML xml,@Pattern varchar(max),@Default varchar(100))
    Returns varchar(max)
    Begin
        Select @Pattern = Replace(@Pattern,Item,Value)
         From (
                Select Item   = '[['+attr.value('local-name(.)','varchar(100)')+']]'
                      ,Value  = attr.value('.','varchar(max)') 
                 From  @XML.nodes('/row') as xn(n)
                 Cross Apply xn.n.nodes('./@*') AS xa(attr)
                Union All
                Select Item  = left(Item,charindex(']]',Item)+1)
                      ,Value = @Default 
                 From (
                        Select Item  = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(max)')))
                        From  (Select x = Cast('<x>' + replace((Select replace(replace(@Pattern,'[[','||[['),'||','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
                        Cross Apply x.nodes('x') AS B(i)
                      ) P 
                 Where charindex('[[',Item)>0 and charindex(']]',Item)>0
              ) A 
    
        Return ltrim(rtrim(replace(replace(replace(@Pattern,' ','><'),'<>',''),'><',' ')))
    End
    
      

    编辑 - 不需要交叉申请

    Select ID
          ,Formatted = [dbo].[udf-Str-Tokenize]((Select A.* for XML Raw),@Pattern,' ')
     From  @YourTable A