如果您使用客户名称,那么您真的应该使用 NVARCHAR 而不是 VARCHAR,因为您不能保证名称只会包含美国英文字符(即“A”-“Z”)加上一些什锦重音字符(我假设您使用的是默认排序规则 *Latin1_General*,而 VARCHAR 数据又使用代码页 1252)。
也就是说,有 很多 字符在名称中是有效的(通常是字母,但也有连字符和逗号),而 很多 字符是无效的.尝试指定任一组,即使是字符类中的一系列字符(即[...]),每次出现新字符时都可能需要更新。
处理此问题的一种简单方法是使用正则表达式(即 RegEx,不,LIKE 和 PATINDEX 函数的[...] 通配符不是正则表达式,不不管有多少人这样称呼它)。 SQL Server 本身不支持 RegEx,但您可以通过 SQLCLR 获得该功能,该功能适用于从 2005 开始的所有版本的所有本地版本(包括 Linux 上的 SQL Server)和 Azure SQL 数据库托管实例;它仅在常规 Azure SQL 数据库和 AWS SQL Server RDS(从 2017 版开始)上不可用。获取 RegEx 的一个简单方法是下载并安装 SQL#,这是我创建的一个 SQLCLR 库(大部分 RegEx 函数都在免费版本中,包括我将在下面使用的)。
正则表达式不仅可以处理复杂的模式(比我们在这里处理的要复杂得多),而且它们还允许我们指定 Unicode“类别”。对于这种特殊情况,我们只需要使用“字母”类别,其中包括大写、小写和其他形式的字母。单独使用这个类别也会删除连字符和逗号,因为我们可能不想这样做(因为它们在名称中是有效的),我们可以轻松地将它们重新添加。
我们将使用的表达式是:[^\p{L}, -]。这个模式读作:
-
[^...] = 找到与此列表中的字符不匹配的任何单个字符
-
\p{L} = 匹配任何归类为“字母”的字符(在任何语言中,这就是为什么这样有效)
-
, - = 匹配逗号、空格和连字符。由于连字符在字符类中用于表示范围,因此如果要用作文字连字符,它们必须是第一个字符或最后一个字符。
这将我们带到以下示例:
SELECT SQL#.RegEx_Replace4k(
N'a .` ''b$c d ef-ghi,jr. ꓤ ඖ ל ؼ ញ z', -- string to modify
N'[^\p{L}, -]', -- regular expression (pattern)
N'', -- replacement
-1, -- number of occurrences to replace (-1 = unlimited)
1, -- character position to start at
NULL -- RegEx options (such as case-insensitive, multi-line, etc)
);
--a bc d ef-ghi,jr ꓤ ඖ ל ؼ ញ z
当然,这仍然给我们留下了一个没有其他答案(正确)解决的问题:将多个空格转换为一个空格。
在问题中,您设置了 REPLACE 以将两个空格转换为一个空格。这只有在 only 两个空格的情况下才有效。如果有三个或更多空格,那么它只会转换每两个一组,这仍然会给您留下多个空格。例如:
SELECT REPLACE(N'a b', N' ', N' ') AS [3 spaces],
REPLACE(N'a b', N' ', N' ') AS [4 spaces],
REPLACE(N'a b', N' ', N' ') AS [5 spaces];
/*
3 spaces 4 spaces 5 spaces
a b a b a b
*/
如您所见,“3”和“4”空格测试都留下两个空格,而“5”空格测试留下三个空格。
这是 RegEx 非常适合的另一种操作类型。您可以指定一个模式以匹配“两个或多个空格”,然后它将处理任意数量的空格并将匹配的任何内容替换为单个空格,无论是 2、3 还是 27 个空格。我们可以使用\s{2,} 表示“两个或多个空白字符”或\s\s+ 表示“一个空白字符后跟一个或多个空白字符”的模式。
例如,如果我们从上一个 RegEx 测试的输出开始,我们可以执行以下操作:
SELECT SQL#.RegEx_Replace4k(
N'a bc d ef-ghi,jr ꓤ ඖ ל ؼ ញ z', N'\s{2,}',
N' ',
-1, 1, NULL);
--a bc d ef-ghi,jr ꓤ ඖ ל ؼ ញ z