表达式在字符串中查找多个空格

Fra*_*kje 2 t-sql sql-server string

我们处理了很多敏感数据,我想仅使用每个名称部分的第一个和最后一个字母来掩盖乘客姓名,并将它们连接成三个星号(***),

例如:'John Doe'这个名字将成为'J***n D***e'

对于由两部分组成的名称,可以通过使用表达式查找空间来实现:

LEFT(CardHolderNameFromPurchase, 1) + 
 '***' + 
 CASE WHEN CHARINDEX(' ', PassengerName) = 0 
      THEN RIGHT(PassengerName, 1) 
      ELSE SUBSTRING(PassengerName, CHARINDEX(' ', PassengerName) -1, 1) +
           ' ' + 
           SUBSTRING(PassengerName, CHARINDEX(' ', PassengerName) +1, 1) +
           '***' + 
           RIGHT(PassengerName, 1) 
 END
Run Code Online (Sandbox Code Playgroud)

但是,乘客姓名可以有两个以上的部分,没有实际限制.我怎样才能找到表达式中所有空格的索引?或者我应该以不同的方式解决这个问题?

非常感谢任何帮助或指针!

iam*_*ave 5

这个解决方案可以满足您的需求,但在尝试隐藏可识别个人身份的数据时,这种方法确实是错误的,正如Gordon在他的回答中所解释的那样.

SQL:

declare @t table(n nvarchar(20));
insert into @t values('John Doe')
,('JohnDoe')
,('John Doe Two')
,('John Doe Two Three')
,('John O''Neill');

select n
      ,stuff((select ' ' + left(s.item,1) + '***' + right(s.item,1)
              from dbo.fn_StringSplit4k(t.n,' ',null) as s
              for xml path('')
              ),1,1,''
              ) as mask
from @t as t;
Run Code Online (Sandbox Code Playgroud)

输出:

+--------------------+-------------------------+
|         n          |          mask           |
+--------------------+-------------------------+
| John Doe           | J***n D***e             |
| JohnDoe            | J***e                   |
| John Doe Two       | J***n D***e T***o       |
| John Doe Two Three | J***n D***e T***o T***e |
| John O'Neill       | J***n O***l             |
+--------------------+-------------------------+
Run Code Online (Sandbox Code Playgroud)

基于Jeff Moden的Tally Table方法的字符串拆分功能:

create function [dbo].[fn_StringSplit4k]
(
  @str nvarchar(4000) = ' '    -- String to split.
 ,@delimiter as nvarchar(1) = ','  -- Delimiting value to split on.
 ,@num as int = null      -- Which value to return, null returns all.
)
returns table
as
return
     -- Start tally table with 10 rows.
 with n(n)   as (select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1)

     -- Select the same number of rows as characters in @str as incremental row numbers.
     -- Cross joins increase exponentially to a max possible 10,000 rows to cover largest @str length.
  ,t(t)   as (select top (select len(isnull(@str,'')) a) row_number() over (order by (select null)) from n n1,n n2,n n3,n n4)

     -- Return the position of every value that follows the specified delimiter.
  ,s(s)   as (select 1 union all select t+1 from t where substring(isnull(@str,''),t,1) = @delimiter)

     -- Return the start and length of every value, to use in the SUBSTRING function.
     -- ISNULL/NULLIF combo handles the last value where there is no delimiter at the end of the string.
  ,l(s,l) as (select s,isnull(nullif(charindex(@delimiter,isnull(@str,''),s),0)-s,4000) from s)

 select rn
          ,item
 from(select row_number() over(order by s) as rn
    ,substring(@str,s,l) as item
  from l
  ) a
 where rn = @num
  or @num is null;
GO
Run Code Online (Sandbox Code Playgroud)