背景
有些開發(fā)人員在做跨系統(tǒng)傳輸數(shù)據(jù)時,偶爾會遇到字符串中包含不可見字符的情況,導(dǎo)致無法在sql的where條件里精確檢索這條數(shù)據(jù),只能用like模糊查找,比如下面這個數(shù)據(jù)

分析
兩行中,A列的值看上去是一樣的,但是下面這條sql,卻只能查出一條記錄

對比下字符串長度,發(fā)現(xiàn)長度不一致

稍微有點(diǎn)經(jīng)驗的會說,這不就一個空格、回車或者換行嘛。
但是當(dāng)你用光標(biāo)上下左右移動去數(shù)能移動幾次時,發(fā)現(xiàn)的確只能數(shù)出來3個,多的那個字符是真的"不可見"!它既不是回車也不是換行!用trim函數(shù)也無法去除!

這個時候,如果去比較這兩個值的十六進(jìn)制數(shù)據(jù),你就會發(fā)現(xiàn)區(qū)別在哪里
select t.*,length(a),utl_raw.cast_to_raw(a)
from txt_test t;

對照ascii碼表,十六進(jìn)制的61是a,62是b,63是c

而00是個空字符

這下我們找到不一致的原因了,但我們要如何才能把這個多余的字符去掉呢?
去掉字符,常見的有substr截取、replace替換、translate翻譯等函數(shù),本例的空字符是在最后,用substr看上去把最后一個字符截掉就好了,但是如果這個字符是位置隨機(jī)數(shù)量隨機(jī)出現(xiàn)在字符串的任意位置,很明顯substr就不適用了,那么此時就應(yīng)該用replace。
可是,replace的三個參數(shù)中,第一個參數(shù)是原字符串,第二個參數(shù)是要查找的字符串,第三個參數(shù)是要替換成的字符串,第一個和第三個好說,但這第二個參數(shù)填什么?填’00’?
'00’肯定不行,'00’只是個字符串而已。
處理
上面說了,這些值是對照ascii碼的,在oracle中,我們可以使用ascii函數(shù)來獲得一個字符的ascii碼(十進(jìn)制),也可以通過chr函數(shù)將一個ascii碼(十進(jìn)制)轉(zhuǎn)成對應(yīng)的字符,所以我們不需要真正的把這個字符給輸入出來,只要使用chr(0)來作為參數(shù)即可。
select t.*,length(a),replace(a,chr(0)),length(replace(a,chr(0)))
from txt_test t;

總結(jié)
本文中以00這個ascii碼為例,介紹了如何識別不可見字符,以及如何處理不可見字符。但在ascii碼中,還有很多不可見字符或者不好用鍵盤輸入的字符,什么換行、tab之類的,處理方法都是類似的。只要我們檢查這個字符串的十六進(jìn)制數(shù)據(jù),就能知道這個特殊字符的ascii碼(十六進(jìn)制)是多少,然后再對照ascii碼表即可知道它是什么東西。最后,如果要去掉這個字符,只需要使用replace加chr函數(shù)即可,比如replace(a,chr(10))去掉換行,replace(a,chr(13))去掉回車。
附本文中的實驗數(shù)據(jù)生成sql
create table txt_test (id number,a varchar2(20));
insert into txt_test values (1,'abc');
insert into txt_test values (2,'abc'||chr(0));
commit;
- 本文作者: DarkAthena
- 本文鏈接: https://www.darkathena.top/archives/invisible-character-replace
- 版權(quán)聲明: 本博客所有文章除特別聲明外,均采用CC BY-NC-SA 3.0 許可協(xié)議。轉(zhuǎn)載請注明出處!




