客户端和服务器端均使用AL32UTF8字符集遇到的问题

下文参考网友“yangzb"的博文(http://yangzb.iteye.com/blog/255769 )整理而成。


服务器端使用AL32UTF8字符集,客户端使用的字符集为GBK,但客户端的字符集设置为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;

如果客户端和服务器端都是 AL32UTF8的情况,Oracle检查数据库与客户端的字符集设置是同样的,那么数据在客户与数据库之间的存取过程中将不发生任何转换,所有录入到数 据库中的内容实际上是以gbk编码的,在读取的时候由于客户端和服务器端的字符集一致,所有也不会发生字符集的转换,读出的也是gbk的编码。当客户端设 置的字符集是gbk时, 服务器端判断出两边的字符集不符合,所以会将gbk编码转换成utf-8的编码,同时客户端在读取时,会将utf-8的编码转成gbk编码,这样就保证了 中文输入的正确性。
之所以出现前面的现象,是因为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

虽然我们在客户端将字符集设置为al32utf8,但客户端实际使用的字符集还是操作系统的字符集,即GBK。而我们在客户端设置的al32utf8只是一个标志,用来告诉服务器,我这里用的是al32utf8的字符集。所以,这时就发生了服务器认为客户端与服务器端所使用的字符集是相同的,是无需做代码转换的。
而‘管’字的GBk编码是b9 dc(转换为二进制是10111001 11011100),由于B9不在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'对应的二进制编码为:11000000

’ED'对应的二进制编码为:11101101
读取的顺序 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)

综上,当我们设置客户端的字符集时,是要根据客户端的实际情况而设置,而不是把服务器端的字符集设置成客户端的。否则,就会出现类似上文所述的问题。


你可能感兴趣的:(客户端,ORA-01756,AL32UTF8)