SQL Server 2016中DISTINCT与TRIM无法消除左侧空白问题求助
解决SQL Server 2016中TRIM/DISTINCT无法去除特殊空白重复项的问题
你遇到的核心问题是:这些"左侧空白"不是普通空格(ASCII 32),而是非标准空白字符(比如不间断空格ASCII 160、制表符ASCII 9、换行/回车符ASCII 10/13等),SQL Server的TRIM/LTRIM/RTRIM默认只处理普通空格,因此这些特殊字符会被保留,导致DISTINCT判定为不同值。
以下是具体解决步骤:
1. 排查特殊字符类型
先执行以下语句,查看异常值的第一个字符ASCII码和长度变化,确定是哪种特殊字符:
SELECT line_of_bus, ASCII(LEFT(line_of_bus, 1)) AS first_char_ascii, LEN(line_of_bus) AS original_len, LEN(LTRIM(line_of_bus)) AS after_ltrim_len FROM contract_info WHERE contract_yr = i_year AND line_of_bus LIKE ' %' -- 筛选开头带空白的记录
- 如果
first_char_ascii是160:是不间断空格 - 如果是9:是制表符
- 如果是10/13:是换行/回车符
2. 针对性清理并去重
根据排查结果,替换对应特殊字符后再使用TRIM和DISTINCT:
处理不间断空格(最常见情况)
SELECT DISTINCT TRIM(REPLACE(line_of_bus, CHAR(160), ' ')) AS cleaned_line_of_bus FROM contract_info WHERE line_of_bus IS NOT NULL AND TRIM(REPLACE(line_of_bus, CHAR(160), ' ')) <> '' AND contract_yr = i_year
处理制表符、换行/回车
SELECT DISTINCT TRIM( REPLACE( REPLACE( REPLACE(line_of_bus, CHAR(9), ' '), -- 替换制表符 CHAR(10), ' '), -- 替换换行符 CHAR(13), ' ') -- 替换回车符 ) AS cleaned_line_of_bus FROM contract_info WHERE line_of_bus IS NOT NULL AND TRIM( REPLACE( REPLACE( REPLACE(line_of_bus, CHAR(9), ' '), CHAR(10), ' '), CHAR(13), ' ') ) <> '' AND contract_yr = i_year
通用清理(覆盖多数特殊空白场景)
合并替换多种常见特殊空白字符,确保全面清理:
SELECT DISTINCT LTRIM(RTRIM( REPLACE( REPLACE( REPLACE( REPLACE(line_of_bus, CHAR(9), ' '), CHAR(10), ' '), CHAR(13), ' '), CHAR(160), ' ') )) AS cleaned_line_of_bus FROM contract_info WHERE line_of_bus IS NOT NULL AND LTRIM(RTRIM( REPLACE( REPLACE( REPLACE( REPLACE(line_of_bus, CHAR(9), ' '), CHAR(10), ' '), CHAR(13), ' '), CHAR(160), ' ') )) <> '' AND contract_yr = i_year
3. 长期优化建议
如果是数据录入环节引入的特殊字符,建议:
- 在插入/更新数据时,提前清理这些特殊字符(比如在应用层或触发器中处理)
- 给表添加计算列,存储清理后的
line_of_bus值,后续查询直接使用计算列,提升效率
内容的提问来源于stack exchange,提问作者datboiluiskrrt
相关产品推荐
相关产品推荐

