oracle資料庫之base64編碼
這幾天在做一個數據庫業務時,需要用到oracle資料庫的系統函式utl_encode.base64_encode()。由於之前沒用過,就從網上找了一些相關的資料以作參考,網上大部分沒有過多地介紹,基本只給出以下用法:
1.base64 的解碼函式
select utl_raw.cast_to_varchar2(utl_encode.base64_decode(utl_raw.cast_to_raw(‘YWJjZA==’))) from dual
2.base64 的編碼函式
select utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(‘abcd’))) from dual
上述用法沒有問題,出現問題的是utl_encode.base64_encode()這個函式。這個函式經過試驗發現,當其輸入引數的字元個數(這裡只考慮英文字元,中文字元的話應該考慮其位元組數)大於等於48時,編碼生成的字串以64個字元為一組在其後添加回車換行字元
這是我的環境:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bi
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
這是驗證方式(直接複製到sqlplus上執行):
三個星號(*)是為了直觀地顯示出有無回車換行符而加在字串末尾。
declare
strBefore1 varchar2(100) := '123456789012345678901234567890123456789012345678';
strAfter1 varchar2(100);
strBefore2 varchar2(100) := '12345678901234567890123456789012345678901234567';
strAfter2 varchar2(100);
strBefore3 varchar2(100 ) := '1234567890123456789012345678901234567890123456789';
strAfter3 varchar2(100);
begin
strAfter1 := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(strBefore1)));
strAfter2 := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(strBefore2)));
strAfter3 := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(strBefore3)));
dbms_output.put_line('length of strBefore1:' || length(strBefore1));
dbms_output.put_line('length of strAfter1:' || length(strAfter1));
dbms_output.put_line('strBefore1:');
dbms_output.put_line(strBefore1 || '***');
dbms_output.put_line('strAfter1:');
dbms_output.put_line(strAfter1 || '***');
dbms_output.put_line('length of strBefore2:' || length(strBefore2));
dbms_output.put_line('length of strAfter2:' || length(strAfter2));
dbms_output.put_line('strBefore2:');
dbms_output.put_line(strBefore2 || '***');
dbms_output.put_line('strAfter2:');
dbms_output.put_line(strAfter2 || '***');
dbms_output.put_line('length of strBefore3:' || length(strBefore3));
dbms_output.put_line('length of strAfter3:' || length(strAfter3));
dbms_output.put_line('strBefore3:');
dbms_output.put_line(strBefore3 || '***');
dbms_output.put_line('strAfter3:');
dbms_output.put_line(strAfter3 || '***');
end;
/
這是實驗結果:
從結果中可以看出strAfter31和strAfter3字串中插有回車換行符,要證明是這兩個字元,各位可自行通過substr()函式(獲取子串)和ascii()函式獲取多出的兩個字元的ascii值。另外提一點,正常的base64編碼後的字串的長度是4的倍數。
對此問題我沒有找到相關資料,oracle官方文件也沒有說明。
文件地址:http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/u_encode.htm#CACECFHF
length of strBefore1:48
length of strAfter1:66
strBefore1:
123456789012345678901234567890123456789012345678***
strAfter1:
MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4
***
length of strBefore2:47
length of strAfter2:64
strBefore2:
12345678901234567890123456789012345678901234567***
strAfter2:
MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc=***
length of strBefore3:49
length of strAfter3:70
strBefore3:
1234567890123456789012345678901234567890123456789***
strAfter3:
MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4
OQ==***
PL/SQL procedure successfully completed.
解決辦法:
要解決這個問題其實很簡單(當時想複雜了,本想分組逐個去掉回車換行符),就是使用替換函式
1. regexp_replace(source_string, expression [, replace_string [, position [, occurrence [, match_parameter]]]])
這是一個正則表示式替換函式。
source_stirng 待搜尋的字串。
expression 一個用來描述要尋找文字的模式的正則表示式。
replace_string 查詢替換中要替換成的文字。
position 源字串source_string中搜索開始的字元位置。預設是1。
occurrence 要定位的模式出現的次數。預設是1,也就是第一次匹配。
match_parameter 這個字串指定選項,改變正則表示式匹配引擎的行為。
針對當前問題的用法:regexp_replace(strAfter, '\s', '')
'\s'會匹配所有空白字元,包括回車符、換行符、製表符、垂直製表符、跳頁符、空格等。
2. replace(string1, match_string, replace_string)
這是一個普通的替換函式。把字串string1中的match_string替換為replace_string,並返回替換後的字串。這一函式同時實現了查詢替換功能。
針對當前問題的用法:replace(strAfter, chr(10) || chr(13), '')
chr(10)表示換行符;chr(13)表示回車符。
3. replace(string1, match_string)
這是一個普通的替換函式。把string1中的所有match_string都刪除掉並返回刪除後的字串。
針對當前問題的用法:replace(strAfter, chr(10) || chr(13))
注:這三個函式的解釋摘抄自《oracle PL/SQL程式設計 第五版》上冊216頁,下冊1097頁。
這裡只用了正則表示式替換函式,好處是所有空白都能替換為空字元,而不管是否是回車換行字元。
declare
strBefore1 varchar2(100) := '123456789012345678901234567890123456789012345678';
strAfter1 varchar2(100);
strBefore2 varchar2(100) := '12345678901234567890123456789012345678901234567';
strAfter2 varchar2(100);
strBefore3 varchar2(100) := '1234567890123456789012345678901234567890123456789';
strAfter3 varchar2(100);
begin
strAfter1 := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(strBefore1)));
strAfter2 := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(strBefore2)));
strAfter3 := utl_raw.cast_to_varchar2(utl_encode.base64_encode(utl_raw.cast_to_raw(strBefore3)));
strAfter1 := regexp_replace(strAfter1, '\s', '');
strAfter2 := regexp_replace(strAfter2, '\s', '');
strAfter3 := regexp_replace(strAfter3, '\s', '');
dbms_output.put_line('length of strBefore1:' || length(strBefore1));
dbms_output.put_line('length of strAfter1:' || length(strAfter1));
dbms_output.put_line('strBefore1:');
dbms_output.put_line(strBefore1 || '***');
dbms_output.put_line('strAfter1:');
dbms_output.put_line(strAfter1 || '***');
dbms_output.put_line('length of strBefore2:' || length(strBefore2));
dbms_output.put_line('length of strAfter2:' || length(strAfter2));
dbms_output.put_line('strBefore2:');
dbms_output.put_line(strBefore2 || '***');
dbms_output.put_line('strAfter2:');
dbms_output.put_line(strAfter2 || '***');
dbms_output.put_line('length of strBefore3:' || length(strBefore3));
dbms_output.put_line('length of strAfter3:' || length(strAfter3));
dbms_output.put_line('strBefore3:');
dbms_output.put_line(strBefore3 || '***');
dbms_output.put_line('strAfter3:');
dbms_output.put_line(strAfter3 || '***');
end;
/
這是上述解決辦法的實驗結果:
length of strBefore1:48
length of strAfter1:64
strBefore1:
123456789012345678901234567890123456789012345678***
strAfter1:
MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4***
length of strBefore2:47
length of strAfter2:64
strBefore2:
12345678901234567890123456789012345678901234567***
strAfter2:
MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc=***
length of strBefore3:49
length of strAfter3:68
strBefore3:
1234567890123456789012345678901234567890123456789***
strAfter3:
MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQ==***
PL/SQL procedure successfully completed.
上述說明如有問題,歡迎批評指正。