NCHAR列查询返回冗余数据,RTRIM无法去除尾部特殊空格求助
这个问题我碰到过好几次——固定长度的NCHAR字段加上特殊空白字符确实会搞砸DISTINCT查询,普通的RTRIM根本不管用。咱们一步步来解决:
第一步:先搞清楚到底是什么“特殊空格”
RTRIM只对普通空格(Unicode U+0020)生效,既然它没用,说明尾部的是其他空白字符(比如非-breaking空格U+00A0,或者各种Unicode宽空格)。先拿一条有问题的记录,查尾部字符的编码值:
-- 取一条匹配条件的记录,查看最后一个字符的Unicode编码 SELECT UNICODE(RIGHT([RULE], 1)) AS TrailingCharUnicode FROM MYTBL WHERE [RULE] LIKE N'Trademarks, logos, slogans, company names, copyrighted material or brands of any third party%'
执行后得到的数字就是这个字符的编码,比如160对应U+00A0(最常见的情况),8192对应U+2000宽空格等等。
第二步:针对性清理字符并去重
根据查到的编码,咱们可以用REPLACE把特殊空白替换成普通空格,再用RTRIM/LTRIM清理,最后做DISTINCT:
如果是U+00A0(非-breaking空格,编码160)
SELECT DISTINCT -- 先替换特殊空格,再去除首尾普通空格 LTRIM(RTRIM(REPLACE([RULE], NCHAR(0x00A0), N''))) AS CleanedRule, -- 计算清理后的长度 LEN(LTRIM(RTRIM(REPLACE([RULE], NCHAR(0x00A0), N'')))) AS CleanedRuleLength FROM MYTBL WHERE [RULE] LIKE N'Trademarks, logos, slogans, company names, copyrighted material or brands of any third party%'
注意这里LIKE后面要加N前缀,因为是NCHAR类型的字段,确保匹配的是Unicode字符串。
如果是多种特殊空白(SQL Server 2017+)
如果不确定是哪一种,或者字段里混了多种空白字符,可以用TRANSLATE一次性把常见的Unicode空白都转成普通空格,再清理:
-- 定义所有常见的Unicode空白字符 DECLARE @WhiteSpaceChars NVARCHAR(200) = NCHAR(0x00A0) + NCHAR(0x2000) + NCHAR(0x2001) + NCHAR(0x2002) + NCHAR(0x2003) + NCHAR(0x2004) + NCHAR(0x2005) + NCHAR(0x2006) + NCHAR(0x2007) + NCHAR(0x2008) + NCHAR(0x2009) + NCHAR(0x200A) + NCHAR(0x202F) + NCHAR(0x205F) + NCHAR(0x3000); SELECT DISTINCT LTRIM(RTRIM(TRANSLATE([RULE], @WhiteSpaceChars, REPLICATE(N' ', LEN(@WhiteSpaceChars))))) AS CleanedRule, LEN(LTRIM(RTRIM(TRANSLATE([RULE], @WhiteSpaceChars, REPLICATE(N' ', LEN(@WhiteSpaceChars)))))) AS CleanedRuleLength FROM MYTBL WHERE [RULE] LIKE N'Trademarks, logos, slogans, company names, copyrighted material or brands of any third party%'
TRANSLATE会把@WhiteSpaceChars里的每一个字符都替换成对应的普通空格,之后RTRIM/LTRIM就能正常工作了。
为什么会出现这种情况?
你用的是NCHAR(120),这是固定长度的Unicode字符类型——如果实际内容长度不足120,SQL Server会自动补**普通空格(U+0020)**到120位。但这里RTRIM没用,说明数据在插入的时候就被加上了特殊空白(比如从Excel复制粘贴带过来的非-breaking空格),或者后续的更新操作引入了这些字符,导致普通的RTRIM无法识别。
内容的提问来源于stack exchange,提问作者RahulGo8u

