应用报出了异常,发现某表某字段下的数据多了些字符,但是在数据库中用sql查看时不一定能够发现。这种情况一般是在字符结尾多了空格、制表符、回车符、换行符等造成。可以从数据库中校验并修正这些异常数据。
基础知识
特殊字符ascii码,Oracle和MySQL中的表示方法:
特殊符号 |
Oracle |
MySQL |
TiDB |
空格 |
chr(32) |
char(32) |
char(32) |
制表符 |
chr(9) |
char(9) |
char(9) |
回车符 |
chr(13) |
char(13) |
char(13) |
换行符 |
chr(10) |
char(10) | char(10) |
更多ascii码可参考https://blog.csdn.net/u010033674/article/details/113033220
Oracle中可以用ascii函数查看对应的ascii码:
select ascii(' ') from dual; 32 select ascii('&') from dual; 38
MySQL中也有对应的函数:
select ascii(' '); +------------+ | ascii(' ') | +------------+ | 32 | +------------+ select ascii('&'); +------------+ | ascii('&') | +------------+ | 38 | +------------+
揪出问题数据
创建测试数据:
Oracle 11.2测试表:
create table test_char ( id int, name varchar2(50), note varchar2(50) );
MySQL 5.7、TiDB 3.0测试表:
drop table test_char; create table test_char ( id int, name varchar(50), note varchar(50) ) ;
分别在不同类型数据库中插入测试数据:
--oracle INSERT INTO test_char VALUES (1,'0123456789 ','空格'); INSERT INTO test_char VALUES (2,'0123456789'||chr(9),'制表符'); INSERT INTO test_char VALUES (3,'0123456789'||chr(10),'回车符'); INSERT INTO test_char VALUES (4,'0123456789'||chr(13),'换行符'); commit; --mysql/tidb INSERT INTO test_char VALUES (1,'0123456789 ','空格'); INSERT INTO test_char VALUES (2,concat('0123456789',char(9)),'制表符'); INSERT INTO test_char VALUES (3,concat('0123456789',char(10)),'回车符'); INSERT INTO test_char VALUES (4,concat('0123456789',char(13)),'换行符');
--oracle中检查出异常数据
select id,name,length(name),note, case when name like '% %' then '有空格' when name like '%'||chr(9)||'%' then '有制表符' when name like '%'||chr(13)||'%' then '有换行符' when name like '%'||chr(10)||'%' then '有回车符' end as chk_teshu from test_char;
从检查结果中可以看出,name字段中期望的是10个字符,length函数检查出来是11个字符,多了一个看不见的字符,通过like匹配,检查出对应的特殊字符。
--mysql/tidb中检查异常数据
select id,name,length(name),note, case when name like '% %' then '有空格' when name like concat('%',char(9),'%') then '有制表符' when name like concat('%',char(13),'%') then '有换行符' when name like concat('%',char(10),'%') then '有回车符' end as chk_teshu from test_char;
从mysql/tidb检查结果中看到,和oracle一样,name字段中期望的是10个字符,length函数检查出来是11个字符,多了一个看不见的字符,通过like匹配,检查出对应的特殊字符。
清洗问题数据
--使用replace函数替换掉多余的特殊字符
--oracle update test_char set name =replace(name,chr(9),''); update test_char set name =replace(name,chr(10),''); update test_char set name =replace(name,chr(13),''); --mysql/tidb update test_char set name =replace(name,char(9),''); update test_char set name =replace(name,char(10),''); update test_char set name =replace(name,char(13),'');