使用AL32UTF8字符集遇到的问题

: 使用AL32UTF8字符集遇到的问题

Arrayxipipku
中级会员



精华贴数 0
个人空间 0
技术积分 624 (3067)
社区积分 2 (24995)
注册日期 2004-5-11
论坛徽章:2
       
           
#1
使用道具   
发表于 2005-4-13 17:16 
使用AL32UTF8字符集遇到的问题

客户端的字符集也设置为AL32UTF8,执行语句时出现一下问题:

SQL>  update t_port_permission set permission_name='删除入库' where permission_name='123';
ERROR:
ORA-01756: quoted string not properly terminated


SQL> update t_port_permission set permission_name='删除管理员' where permission_name='123';

1 row updated.

SQL> commit;

Commit complete.

SQL> update t_port_permission set permission_name='管理员管理' where permission_name='234';
ERROR:
ORA-01756: quoted string not properly terminated
SQL> update t_port_permission set permission_name='操作员' where permission_name='234';

1 row updated.

SQL> commit;

有写中文组合能进去,有些不可以,将sql写出脚本执行也是一样的效果,怎么去解决这个问题,最好是能告诉一下分析的思路。


只看该作者   
bachang
初级会员



精华贴数 0
个人空间 0
技术积分 48 (28339)
社区积分 0 (62519)
注册日期 2002-8-13
论坛徽章:0
           
           
#2
使用道具   
发表于 2005-4-13 17:28 
你可以設定為AMERICAN_AMERICA.ZHS16GBK試試


只看该作者   
xipipku
中级会员



精华贴数 0
个人空间 0
技术积分 624 (3067)
社区积分 2 (24995)
注册日期 2004-5-11
论坛徽章:2
       
           
#3
使用道具   
发表于 2005-4-13 17:57 
使用AMERICAN_AMERICA.ZHS16GBK进行读取是没问题,但我主要是想知道为什么,我分析了一下在ZHS16GBK环境中数据库存储的信息情况:
SQL> insert into test values('删除');

1 row created.

SQL> select dump(name) from test;

DUMP(NAME)
--------------------------------------------------------------------------------
Typ=1 Len=6: 229,136,160,233,153,164

可以看出在数据库中每个汉字的存储是三个字节,编码方式实际上是UTF-8的编码。

再看一下AL32UTF8字符集时候的情况:
SQL> insert into test values('删除');

1 row created.

SQL> select dump(name) from test;

DUMP(NAME)
--------------------------------------------------------------------------------
Typ=1 Len=4: 201,190,179,253
可以看到,每个汉字的编码实际上是按照gb2312进行的编码

与我一开始的想法正好想反,谁能帮我分析一下这整个过程,从客户端录入到存储再到读出。


只看该作者   
sydongsun
高级会员



精华贴数 0
个人空间 0
技术积分 4101 (353)
社区积分 95 (3561)
注册日期 2003-7-5
论坛徽章:10
   
#4
使用道具   
发表于 2005-4-13 18:12 
几乎没有将客户端设置为AMERICAN_AMERICA.AL32UTF8的,在正常情况下,这个参数中的是字符集要反映你的操作系统所采用的字符集的。windows下不知道是否有采用这种AL32UTF8的语言设置? 我估计应该没有。

你需要的详细说一说,可以参考:
http://www.askguoyu.com/db/charset.htm

其实是一个特别好的培训课程。我不知道在参加某些培训课程的时候,是否会讲述的这么详细?一般很少。都是让大家看书的来深入学习这部分内容的。


__________________
===============================
= 欢迎访问我的个人网站:分别选择兴趣主题:
= 开始销售:SAPBW顾问培训课程   
= 销售:Oracle备份和恢复详尽的教程   
|| 软件配置管理 || Lotus Domino   || 数据库技术 ||  
=  = 部分在线教程信息:
= DB2基础入门和备份    || SAP ALE || APAP程序设计 || SAP系统管理 || SAP权限控制
===============================
只看该作者   
jeffli73
侠之大者


精华贴数 2
个人空间 0
技术积分 10578 (113)
社区积分 21 (7384)
注册日期 2002-6-17
论坛徽章:1
         
           
#5
使用道具   
发表于 2005-4-13 18:24 
请参考

http://www.itpub.net/showthread.php?threadid=276524
应该对你有帮助


__________________
安能摧眉折腰事权贵,使我不得开心颜天生我才必有用,千金散尽还复来个人BLOG: http://blog.china-pub.com/blog.asp?name=jefflee包括数据库、软件工程、电信及其它方面的个人感悟,如有兴趣,欢迎访问
只看该作者   
xipipku
中级会员



精华贴数 0
个人空间 0
技术积分 624 (3067)
社区积分 2 (24995)
注册日期 2004-5-11
论坛徽章:2
       
           
#6
使用道具   
发表于 2005-4-14 10:27 
谢谢 sydongsun 和 jeffli73 的帮助,看了相关帖子,对字符集的理解更深刻了,分析一下我出现的问题,
如果客户端和服务器端都是 AL32UTF8的情况,Oracle检查数据库与客户端的字符集设置是同样的,那么数据在客户与数据库之间的存取过程中将不发生任何转换,所有录入到数 据库中的内容实际上是以gbk编码的,在读取的时候由于客户端和服务器端的字符集一致,所有也不会发生字符集的转换,读出的也是gbk的编码。当客户端设 置的字符集是gbk时, 服务器端判断出两边的字符集不符合,所以会将gbk编码转换成utf-8的编码,同时客户端在读取时,会将utf-8的编码转成gbk编码,这样就保证了 中文输入的正确性。
但是我还是没有分析出为什么在客户端和服务器端都为utf-8时为什么会出现
SQL> select dump('管') from dual;
ERROR:
ORA-01756: quoted string not properly terminated

管的汉字编码是
SQL>SQL> select dump('管') from dual;

DUMP('管')
---------------------
Typ=96 Len=2: 185,220


  ' 的编码是39
在解析的时候为什么会出现'呢?


只看该作者   
sydongsun
高级会员



精华贴数 0
个人空间 0
技术积分 4101 (353)
社区积分 95 (3561)
注册日期 2003-7-5
论坛徽章:10
   
#7
使用道具   
发表于 2005-4-14 11:24 
问题在于:
在客户端和服务器端都为utf-8时,假如你正确存入了汉字信息到数据库服务器上,一般来说汉字的UTF8的编码为三个byte。然后你的客户端也是 utf-8, 那么不经过转换就会通过select 显示,比如“管”的假定的信息是185,220,148 (这里是随意写的),但是你的客户端是否具有这样的字符集呢?一般的Windows操作系统是不会让你选择一种UTF8的字符集的,要么是GBK的简体中 文,要么是美国标准英文,后者是windows系统的标准英文,或者是日文操作系统等,没有一种使用UTF8的显示和输入的操作系统。

事实上,Unicode编码主要是一种信息存储的编码方式。可以支持世界上主要的语言的所有字符都能够用一个唯一的编码值在表示和存储。在信息来显示和输 入的时候,大家都还是使用各自的语言的。比如,一个网络在线商店,可以接受,中文的,泰问,日本专有字符,蒙古文的操作系统的输入的内容,同一转换成 UTF8存储到数据中,然后各个操作系统要进行读取的时候,也分别按照UTF8 到各自的操作系统编码转换进行读取。现在全世界还没有一种可以同时使用包含所有主要语言的操作系统,在Windows平台可以通过国家语言设置来进行转换 (但是要么是选择中文版,好么是选择英文版,要么是蒙古文....  ,不能同时选择所有,否则我们的键盘的键格数量要大大增加),所以,没有将客户端设 置为语言选择为UTF8的操作系统。

你需要仔细理解,我的回答并不是非常清楚。

另外,从你 select dump('管') from dual, 实际上表示的是你操作系统当前所使用的语言编码是GBT的,应为只有2个byte. 所以你的AMERICAN_AMERICA.ZHS16GBK 只能选择ZHS16GBK, 永远不要选择为UTF8, 只有你想执行数据库的字符集转换的时候,你在exp和imp的时候,为了exp数据的字符集变化,你可以临时让客户端和数据库段一致。 但是几乎很少有从utf8这种unicode转换到非unicode的工作场景的。


__________________
===============================
= 欢迎访问我的个人网站:分别选择兴趣主题:
= 开始销售:SAPBW顾问培训课程   
= 销售:Oracle备份和恢复详尽的教程   
|| 软件配置管理 || Lotus Domino   || 数据库技术 ||  
=  = 部分在线教程信息:
= DB2基础入门和备份    || SAP ALE || APAP程序设计 || SAP系统管理 || SAP权限控制
===============================
只看该作者   
xipipku
中级会员



精华贴数 0
个人空间 0
技术积分 624 (3067)
社区积分 2 (24995)
注册日期 2004-5-11
论坛徽章:2
       
           
#8
使用道具   
发表于 2005-4-15 10:49 


QUOTE:
最初由 sydongsun 发布
问题在于:
在客户端和服务器端都为utf-8时,假如你正确存入了汉字信息到数据库服务器上,一般来说汉字的UTF8的编码为三个byte。然后你的客户端也是 utf-8, 那么不经过转换就会通过select 显示,比如“管”的假定的信息是185,220,148 (这里是随意写的),但是你的客户端是否具有这样的字符集呢?一般的Windows操作系统是不会让你选择一种UTF8的字符集的,要么是GBK的简体中 文,要么是美国标准英文,后者是windows系统的标准英文,或者是日文操作系统等,没有一种使用UTF8的显示和输入的操作系统。

事实上,Unicode编码主要是一种信息存储的编码方式。可以支持世界上主要的语言的所有字符都能够用一个唯一的编码值在表示和存储。在信息来显示和输 入的时候,大家都还是使用各自的语言的。比如,一个网络在线商店,可以接受,中文的,泰问,日本专有字符,蒙古文的操作系统的输入的内容,同一转换成 UTF8存储到数据中,然后各个操作系统要进行读取的时候,也分别按照UTF8 到各自的操作系统编码转换进行读取。现在全世界还没有一种可以同时使用包含所有主要语言的操作系统,在Windows平台可以通过国家语言设置来进行转换 (但是要么是选择中文版,好么是选择英文版,要么是蒙古文....  ,不能同时选择所有,否则我们的键盘的键格数量要大大增加),所以,没有将客户端设 置为语言选择为UTF8的操作系统。

你需要仔细理解,我的回答并不是非常清楚。

另外,从你 select dump('管') from dual, 实际上表示的是你操作系统当前所使用的语言编码是GBT的,应为只有2个byte. 所以你的AMERICAN_AMERICA.ZHS16GBK 只能选择ZHS16GBK, 永远不要选择为UTF8, 只有你想执行数据库的字符集转换的时候,你在exp和imp的时候,为了exp数据的字符集变化,你可以临时让客户端和数据库段一致。 但是几乎很少有从utf8这种unicode转换到非unicode的工作场景的。


谢 谢你的回答,实际上怎么使用字符集这个问题我很清楚了,我只是想解释一下出现的现象而已,想通过这方面的研究加深对字符集编码的理解。事实上UFT8的两 字节编码为:110***** 10******   第一个字节的110和第二个字节的10为标志位。三个字节的编码为:1110***** 10****** 10******,第一个字节的1110和第二、三个字节的10都是标志位,剩下的空间正好可以表示汉字。
我们再来看一下测试的数据情况:
在utf-8的环境下执行:

SQL> select dump('管',16) from dual;
ERROR:
ORA-01756: quoted string not properly terminated
管的16机制编码为:
而‘管’字的GBk编码是b9 dc ,事实上不在utf8二字节和三字节的编码范围中,它是以单字节编码的读取方式,写读b9, 然后再读dc,读到dc的时候,由utf-8的编码规则可以知道是二字节编码的,所以他会把后面的'当成二字节编码的一部分,所以就会出现'缺失的现象

SQL> select dump('管1',16) from dual;

DUMP('管1',16)
----------------------
Typ=96 Len=3: b9,dc,31
读的时候  b9  (dc,31)同样的测试可以看到:
SQL> select dump('理12',16) from dual;

DUMP('理12',16)
-------------------------
Typ=96 Len=4: c0,ed,31,32
读取的顺序 c0 (ed 31 32)

SQL> select dump('理1',16) from dual;
ERROR:
ORA-01756: quoted string not properly terminated
    读取的顺序 c0 (ed 31 39),把引号吃掉了
SQL> select dump('理发',16) from dual;

DUMP('理发',16)
-------------------------
Typ=96 Len=4: c0,ed,b7,a2
          读取的顺序为c0 (ed,b7, a2)

通过上面的分析就很容易知道为什么会出现引号缺省的问题了。通过这个问题的解决对字符集的理解大大加深了,谢谢各位的帮助。


只看该作者   
bachang
初级会员



精华贴数 0
个人空间 0
技术积分 48 (28339)
社区积分 0 (62519)
注册日期 2002-8-13
论坛徽章:0
           
           
#9
使用道具   
发表于 2005-4-15 11:30 
以Oracle文件说法~~~档Client and Server使用同一NLS_LANG时~~~Oracle并不会自动帮你进行资料的转换动作~~~所以会以Client的OS的Language来决 定~~~如是GBK就是GBK码~~~所以当资料库为UTF8时就需以Client的OS的Language不同而有不同的设定


只看该作者   
sydongsun
高级会员



精华贴数 0
个人空间 0
技术积分 4101 (353)
社区积分 95 (3561)
注册日期 2003-7-5
论坛徽章:10
   
#10
使用道具   
发表于 2005-4-15 11:38 


QUOTE:
最初由 xipipku 发布

谢谢你的回答,实际上怎么使用字符集这个问题我很清楚了,我只是想解释一下出现的现象而已,想通过这方面的研究加深对字符集编码的理解。事实上UFT8的 两字节编码为:110***** 10******   第一个字节的110和第二个字节的10为标志位。三个字节的编码为:1110***** 10****** 10******,第一个字节的1110和第二、三个字节的10都是标志位,剩下的空间正好可以表示汉字。
我们再来看一下测试的数据情况:
在utf-8的环境下执行:

SQL> select dump('管',16) from dual;
ERROR:
ORA-01756: quoted string not properly terminated
管的16机制编码为:
而‘管’字的GBk编码是b9 dc ,事实上不在utf8二字节和三字节的编码范围中,它是以单字节编码的读取方式,写读b9, 然后再读dc,读到dc的时候,由utf-8的编码规则可以知道是二字节编码的,所以他会把后面的'当成二字节编码的一部分,所以就会出现'缺失的现象

SQL> select dump('管1',16) from dual;

DUMP('管1',16)
----------------------
Typ=96 Len=3: b9,dc,31
读的时候  b9  (dc,31)同样的测试可以看到:
SQL> select dump('理12',16) from dual;

DUMP('理12',16)
-------------------------
Typ=96 Len=4: c0,ed,31,32
读取的顺序 c0 (ed 31 32)

SQL> select dump('理1',16) from dual;
ERROR:
ORA-01756: quoted string not properly terminated
    读取的顺序 c0 (ed 31 39),把引号吃掉了
SQL> select dump('理发',16) from dual;

DUMP('理发',16)
-------------------------
Typ=96 Len=4: c0,ed,b7,a2
          读取的顺序为c0 (ed,b7, a2)

通过上面的分析就很容易知道为什么会出现引号缺省的问题了。通过这个问题的解决对字符集的理解大大加深了,谢谢各位的帮助。


不过你提到的东西,我很是陌生? 初步读下来,还不是很理解。我需要记住你的这个帖子,将来有机会好好分析你说的内容。

你可能感兴趣的:(Database)