原來Oracle也不喜歡“蜀黍”

jeanron100發表於2015-09-09
今天在部署一個指令碼的時候,碰到了一個奇怪的問題,指令碼執行過程中報了一個ora錯誤
ORA-01756: quoted string not properly terminated
看這個錯誤似乎是哪裡的標點符號出了問題,沒有正確結束,本來這個問題看起來很明顯,很可能是格式的問題,但是奇怪的是插入中文,有的語句可以,有的就不可以。
我們先來看看環境變數的設定,然後復現一下這個問題
$ echo $NLS_LANG
American_America.zhs16gbk
$ locale
LANG=en_US
LC_CTYPE="en_US"
LC_NUMERIC="en_US"
LC_TIME="en_US"
LC_COLLATE="en_US"
LC_MONETARY="en_US"
LC_MESSAGES="en_US"
LC_PAPER="en_US"
LC_NAME="en_US"
LC_ADDRESS="en_US"
LC_TELEPHONE="en_US"
LC_MEASUREMENT="en_US"
LC_IDENTIFICATION="en_US"
LC_ALL=
檢視資料庫字符集

SQL>  select *from database_properties where property_name='NLS_CHARACTERSET'
PROPERTY_NAME                  PROPERTY_VALUE                 DESCRIPTION
------------------------------ ------------------------------ ------------------------------
NLS_CHARACTERSET               ZHS16GBK                       Character set

復現問題
建立一個臨時表test,然後向裡面插入兩條記錄
SQL> create table test(id number,title varchar2(20));
Table created.
第一條記錄沒有問題
SQL> insert into test values(1,'你好'); 
1 row created.
當嘗試插入“蜀黍”的時候就爆了格式錯誤,難道Oracle不喜歡這種稱謂?
SQL> insert into test values(2,'蜀黍');
ERROR:
ORA-01756: quoted string not properly terminated
如果在後面加一個空格,就可以了
SQL> insert into test values(2,'蜀黍 ');
1 row created.
我們來簡單看一下,是否那個空格還在那兒。
SQL>select '>'||title||'<',id from test 
'>'||TITLE||'<'                ID
---------------------- ----------
>蜀黍 <                        2
還不甘心,決定使用trim來格式化一下,語句執行成功,但是沒有效果,空格還在那兒。
刪除第一條記錄,注意力就關注在
delete from test where id=1;
SQL> update test set title=trim(title);
1 row updated.
SQL> select '>'||title||'<',id from test;
'>'||TITLE||'<'                ID
---------------------- ----------
>蜀黍 <                        2
以上的方法和測試都不見效,那就使出大招,看看dump的結果
SQL> select dump(title) from test;
DUMP(TITLE)
--------------------------------------------------------------------------------
Typ=1 Len=7: 232,156,128,233,187,141,32
可以看到末尾顯示是32,是一個空格
SQL> select '>'||chr(32)||'<' from dual;
'>'
---
> <
整個字串佔用了7個位元組,空格佔用一個,即每個漢字佔用3個,這個方式應該是在字符集為UTF-8的情況
檢視客戶端中設定的字符集,還確實就是UTF-8

修改secureCRT的字符集為預設的方式,即支援中文,然後再次插入,就沒有問題了。
SQL> insert into test values(2,'蜀黍 ');
1 row created.
這個時候重新審視資料,發現原來插入的那條記錄已經顯示為亂碼了。說明最開始插入就有字符集的問題了。
SQL> select * from test;
        ID TITLE
---------- --------------------
         2 銍?榛?
         2 蜀黍
使用dump的方式可以看到兩者還是有著天壤之別。
SQL> select dump(title) from test;
DUMP(TITLE)
--------------------------------------------------------------------------------
Typ=1 Len=7: 232,156,128,233,187,141,32
Typ=1 Len=5: 202,241,202,242,32         
這個時候我們再來看一看dump的結果,可以看到在UTF-8的情況是每個漢字佔用3個位元組,在GBK模式下,是佔用2個位元組。
所以字符集的問題總是一個熱點問題,客戶端的設定也尤為重要,需要考慮字符集的相容性。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-1795908/,如需轉載,請註明出處,否則將追究法律責任。

相關文章