概述
此文是作为笔者在实际工作中遇到和解决的一个数据库的问题的记录。
大概的情况是这样的,笔者需要对一批原始业务数据进行处理,基于一些导入的数据,进行关联和信息的更新。数据库使用Postgres,导入的数据的原始形式是Excel,数据库管理工具使用dbeaver。导入的过程,笔者基于方便,直接使用dbeaver的"高级粘贴",在一个临时表中,直接复制了Excel中的表格数据,进行了粘贴录入。

数据导入的过程看起来还是比较顺利的,但进行关联更新的时候,出现了问题,就是无法将原始数据信息和导入进行进行联合查询,明明是相同的信息,就是无法查询出有效记录,当然也无法根据数据关联进行更新操作。
本文的主要内容,就是记录和分析这个问题发生的原因和处理过程,事后总结时发现,这个问题应该还是有代表性的,所以就记录下来分享。
问题和处理
- 问题表现
 
遇到这个问题后,笔者最初的想法,就是构造一个和更新操作相同条件的查询,来检查一下,是否能够正常查询。
这里出现了一个有趣的现象。记录集查询的时候,是有结果的,表明查询语法和执行没有问题。但查询的结果集和预期不符,要少好多条。这个操作的查询条件之一,是中国居民身份证号码的匹配,经过对结果数据的分析发现查询的结果集中,只包括了身份证末尾为"X"的记录。
这个情况就非常奇怪了,从理论上而言,这些记录好像和别的记录应该也没有什么区别。但再想到数据录入的过程,笔者怀疑在录入(复制粘贴)的过程中,对于居民身份证号码的处理是有差异的?再检查数据,验证了笔者的想法(图):

发现问题了吗? 好像这两种记录类型的显示好像有点不一样,第一条记录前面有"东西(空格)"啊?所以有理由怀疑,当从Excel文档中复制粘贴数据的时候,粘贴程序可能会将全数字的身份证号码,当作了"数字"进行处理,并且加入了某些不可见字符;而对于尾字符为"X"的记录,就是正常的字符串了。
了解到这个情况,解决方法就很简单,再做一遍数据处理,记录的前后空格去掉就行了。
- 去除空格和制表符
 
在postgres中,提供了trim函数,可以用于处理字段值前后的空格:
update t set "IDNO" = trim("IDNO") where ....;
但是,操作完成后,仍然不能正确的查询和更新,说明一个问题,那个看起来是空格的"空格",其实不是空格。但如何手动编辑并更新,就是正确的。说明确实是一个不可见字符。
那有可能是制表符吗,那就要使用替换函数了:
update t set "IDNO" = replace("IDNO", '\t','') where ....;
结果仍然不对!这时候,笔者就觉得事情不是那么简单了。
- 识别不可见字符
 
所以笔者想要看看这到底是一个什么东西。笔者找了一个"在线隐藏字符检测及去除工具",所幸的是,这个信息是可以复制粘贴的,粘贴检测后,得到了这么一个结果:

这里看得很清楚,就是在字符串前面,有一个UTF8类型的水平制表符。 前面笔者可能犯了一个错误,就是替换的时候直接使用"\t",但实际上,在这里要表示制表符,应该使用转义,在Postgres中是 E'\t', 所以其实并没有正确的处理。
- 去除制表符和扩展
 
如果只是处理这个水平制表符的问题,那也很简单,就是使用增强的替换方式:
update t set "IDNO" = replace("IDNO", E'\t','') where ....;
但让我们稍微扩展一下,如果想要查询并且去除所有的前后缀不可见字符,甚至字符串中间的不可见字符,就需要使用更高级的正则替换方式了:
            
            
              js
              
              
            
          
          // 查询异常记录
SELECT idno,  regexp_replace(idno, E'([\\x00-\\x1F\\x7F])', '<\\1>', 'g' ) AS visualized
FROM t
WHERE idno  ~ E'[\\x00-\\x1F\\x7F\\u200B-\\u200F\\uFEFF]';
// 更新数据
update t set idno = regexp_replace( idno, E'([\\x00-\\x1F\\x7F])','','g') ... 
        简单的解释一下:
- regexp_replace可以使用正则检索
 - 四个参数分别是搜索字段,替换搜索,替换结果,选项标识
 - 
\\x00-\\x1F\\x7F\],捕获匹配ASCII 码从0到31的控制字符(不可打印字符)和127(DEL)
 - g 标签,替换所有匹配
 
至此,这个问题算是比较完善的解决了,也有很强的通用性。
小结
本文从笔者在工作中遇到的一个数据处理问题出发,讨论了在使用Excel进行数据导入可能遇到的数据格式转换中可能遇到的问题,包括问题的表现,可能的原因和对应的解决和技术处理方案和操作。