从未编码/非英语字符串中查找空格

时间:2019-03-27 04:53:29

标签: sql sql-server tsql sql-server-2012

在我的代码中,我需要以某种指定的格式显示名称,在该格式中,每个字符都应替换为“ *”字符。但是,我不必替换空格。

现在,由于它是日语应用程序,因此名称也可以包含日语空间字符。有什么可以帮助我识别空间字符的通用方法。 我所做的是在fiddle中。

DECLARE @Name NVARCHAR(50) = N'ab cb';
select IIF(LEN(LTRIM(substring(a.Name, v.number, 1))) = 0, substring(a.Name, v.number, 1), '*')
from (select @Name Name) a
join (  SELECT (1 + ones.n + ISNULL(10*tens.n, 0) + ISNULL(100*thausand.n, 0))  Number
      FROM  (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n),
            (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tens(n),
            (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) thausand(n)
  )V on v.Number <= len(a.Name);

SET @Name = N'中山 大地';
select IIF(LEN(LTRIM(substring(a.Name, v.number, 1))) = 0, substring(a.Name, v.number, 1), '*')
from (select @Name Name) a
join (  SELECT (1 + ones.n + ISNULL(10*tens.n, 0) + ISNULL(100*thausand.n, 0))  Number
      FROM  (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n),
            (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tens(n),
            (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) thausand(n)
  )V on v.Number <= len(a.Name);

2 个答案:

答案 0 :(得分:2)

考虑到所有具有空格属性here的字符,必要的查询可能如下所示:

DECLARE @Name NVARCHAR(50) = N'ab cb';
select IIF(LEN(LTRIM(substring(a.Name, v.number, 1))) = 0, substring(a.Name, v.number, 1), '*')
from (select @Name Name) a
join (  SELECT (1 + ones.n + ISNULL(10*tens.n, 0) + ISNULL(100*thausand.n, 0))  Number
      FROM  (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n),
            (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tens(n),
            (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) thausand(n)
  )V on v.Number <= len(a.Name);

SET @Name = N'中山 大地';

with
  wss as (
    select nchar(u) ws
    from(values(0x0009), (0x000A), (0x000B), (0x000C), (0x000D),
               (0x0085), (0x2028), (0x2029), (0x0020), (0x3000),
               (0x1680), (0x2000), (0x2001), (0x2002), (0x2003),
               (0x2004), (0x2005), (0x2006), (0x2008), (0x2009),
               (0x200A), (0x205F), (0x00A0), (0x2007), (0x202F)) ws(u)
  )
select IIF(LEN(LTRIM(substring(a.Name, v.number, 1))) = 0, substring(a.Name, v.number, 1), '*') replace1,
  iif(substring(a.Name, v.number, 1) in (select ws from wss), substring(a.Name, v.number, 1), '*') replace2
from (select @Name Name) a
join (  SELECT (1 + ones.n + ISNULL(10*tens.n, 0) + ISNULL(100*thausand.n, 0))  Number
      FROM  (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n),
            (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tens(n),
            (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) thausand(n)
  )V on v.Number <= len(a.Name);

输出:

+------------------+
| (No column name) |
+------------------+
| *                |
| *                |
|                  |
| *                |
| *                |
+------------------+

+----------+----------+
| replace1 | replace2 |
+----------+----------+
| *        | *        |
| *        | *        |
| *        |          |
| *        | *        |
| *        | *        |
+----------+----------+

使用Rextester在线进行测试。

答案 1 :(得分:0)

这可以在SQL2017中轻松完成。

DECLARE @Name NVARCHAR(50) = N'中山 大地';

SELECT STRING_AGG(replicate('*', LEN(value)), ' ') AS obfuscated
FROM STRING_SPLIT(@name, ' ') 

obfuscated

STRING_SPLIT SQL2016

STRING_AGG SQL2017

但是对于旧版SQL Server,这可能会更具挑战性。

字符串拆分:

DECLARE @Name NVARCHAR(50) = N'ab cd e';

SELECT Split.a.value('.', 'NVARCHAR(MAX)') AS data_field
FROM   ( SELECT CAST('<X>' + REPLACE(@Name, ' ', '</X><X>') + '</X>' AS XML) AS String ) AS A
        CROSS APPLY String.nodes('/X') AS Split(a)

字符串Agg:

SELECT DISTINCT 
  STUFF((SELECT distinct ' ' + t2.data_field
         from (SELECT Split.a.value('.', 'NVARCHAR(MAX)') AS data_field
                FROM   ( SELECT CAST('<X>' + REPLACE(@Name, ' ', '</X><X>') + '</X>' AS XML) AS String ) AS A
                       CROSS APPLY String.nodes('/X') AS Split(a)) t2

            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,0,'') data