2023-08-18|閱讀時間 ‧ 約 4 分鐘

Ascii 0 在資料庫上造成的困擾

    今天在工作時遇到一件奇怪的問題,
    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應該是轉檔程式在不同系統間轉置資料所造成的,
    至於什麼原因,因為已經不可考,所以就沒辦法知道是什麼原因造成的。
    分享至
    成為作者繼續創作的動力吧!
    從 Google News 追蹤更多 vocus 的最新精選內容從 Google News 追蹤更多 vocus 的最新精選內容

    陳楨珽的沙龍 的其他內容

    發表回應

    成為會員 後即可發表留言
    © 2024 vocus All rights reserved.