今天在工作時遇到一件奇怪的問題,
user反映明明欄位開了CHAR(6 byte),但裡面的文字卻只呈現5個byte,使用length去算整個欄位長度,卻顯示是6,
好吧,就來查查看是遇到甚麼問題了。
select dump(BEFORECOSIGNEREMPNO) from A.test
where NURSEGIVEDRUGIDSE IN (289839402,289769909) AND BEFORECOSIGNEREMPNO IS not NULL;
-------------------------------------
Typ=96 Len=6: 0,0,0,0,10,0
Typ=96 Len=6: 80,48,48,50,55,0
看這兩筆資料,很明顯最後一個byte被塞了acciss碼0的字元,
ascii中0代表 空字元 Null character,
理論上,文字欄位不應該有文字後又加了一個null字元,
也難怪套上oracle nvl()來檢查,還真的不會回應任何對應的欄位,
我們來看,真正欄位值為null時的asscii應該是什麼?
create table test1
as
select * from dual;
alter table test1
add a varchar2(1 byte);
insert into test1
select 'x',null from dual;
commit;
select dump(a) from test1;
-------------------------------------
Typ=1 Len=1: 49
NULL
從上面的測試我們知道,真正的NULL欄位dump出來的質應該是NULL,而不是0,
當你程式把null 的ascii值 0 給塞進資料庫裡,對資料庫來說,這個時候欄位有ascii 值,資料庫就不認為是NULL了。
--我們手動塞一個ascii 為0的值到資料庫中(ascii 0 : Null)
update test1 set a=chr(0) where dummy='x';
commit;
select dump(a),nvl(a,'is null'),a.* from test1 a;
-------------------------------------
Typ=1 Len=1: 49 1 X 1
Typ=1 Len=1: 0 x
上面的測試很清楚知道,ascii 0 其實還是有字符的,只是這個字符代表的是null,但對資料庫的欄位來說,欄位不是null的,很繞口對吧?
那空白呢?
我們也來順便測試一下
--我們塞一個ascii 32 來當成空白
insert into test1
select 'y',chr(32) from dual;
--我們塞一個空白字元進去
insert into test1
select 'y',' ' from dual;
commit;
select dump(a),length(a),a.* from test1 a where dummy='y';
-------------------------------------
Typ=1 Len=1: 32 1 y
Typ=1 Len=1: 32 1 y
這邊實驗的結果,我們可以發現,輸入空白,ascii碼為 32,跟你使用chr(32)的方式是一樣的,
所以ascii空白對資料庫來說,就是空白。
估計這個ascii應該是轉檔程式在不同系統間轉置資料所造成的,
至於什麼原因,因為已經不可考,所以就沒辦法知道是什麼原因造成的。