1818IP-服务器技术教程,云服务器评测推荐,服务器系统排错处理,环境搭建,攻击防护等

当前位置:首页 - 数据库 - 正文

君子好学,自强不息!

Oracle字符集讨论的经典版

2022-11-23 | 数据库 | 1818ip | 607°c
A+ A-

提及Oracle字符集可以说是老生常,Oracle字符集问题的引起,主要是因为其的“乱码”问题。而乱码的产生主要是因为客户端和服务器的实际应用的字符集不同,其进行字符集转换而引起的。

不过很多提到了转换,却没有提到这个转换是在哪个阶段和哪里发生的?是在服务器向块里写入数据的时候吗?在客户端还是在服务器端?

正确的答案是,普通字符串转换发生在客户端(具体来说是由OCI LIBRARY完成的),国家字符串经过两次转换,***次发生在客户端,第二次发生在服务器端。下面做个测试:

连接到:

OracleDatabase10gEnterpriseEditionRelease10.2.0.1.0-Production 
WiththePartitioning,RealApplicationClusters,OLAPandDataMiningoptions 
SQL>select*fromnls_database_parameterswhereparameterlike‘%CHARACTERSET%’; 
PARAMETERVALUE 
------------------------------------------------------------ 
NLS_CHARACTERSETZHS16GBK 
NLS_NCHAR_CHARACTERSETAL16UTF16 
SQL>createtablet1(avarchar2(100)); 

表已创建。

SQL>
SQL>insertintot1values(’中’); 

已创建 1 行。

SQL>

在本次连接中,我没有设置NLS_LANG变量。则客户端Oracle字符集为操作系统的缺省字符集ZHS16GBK。通过捕获网络包,可以发现客户端传送给客户端的数据(不能上传图片,郁闷):

00000090000000000000000000000028DB00011C………..(…. 
000000A0696E7365727420696E746F2074312076insert.into.t1.v 
000000B0616C756573202827D6D0272901000000alues.(’..’)…. 
000000C001000000000000000000000000000000……………. 

注意红色的部分,16进制D6 D0正是“中”字的GBK编码。(关于怎么获取汉字的各种编码,暂且略过,如有需要再交流)

现在我们退出SQLPLUS,设置环境变量NLS_LANG:

SQL>rollback;

回退已完成。

SQL>exit 
OracleDatabase10gEnterpriseEditionRelease10.2.0.1.0-Production 
WiththePartitioning,RealApplicationClusters,OLAPandDataMiningoptions 

断开

C:\DocumentsandSettings\Administrator>setnls_lang=american_america.us7ascii 
C:\DocumentsandSettings\Administrator>sqlplustest/test@dmdb 
SQL*Plus:Release10.2.0.1.0-ProductiononMonJan2800:48:412008 
Copyright(c)1982,2005,Oracle.Allrightsreserved. 
Connectedto: 
OracleDatabase10gEnterpriseEditionRelease10.2.0.1.0-Production 
WiththePartitioning,RealApplicationClusters,OLAPandDataMiningoptions 
SQL>insertintot1values(’中’); 
1rowcreated. 

抓获的网络包发现,在SQL提交给服务器之前已经转换了。OCI库认为提交过来的编码是US7ASCII,因此要将转换为服务器端的ZHS16GBK编码,然而“中”的编码即16进制D6 D0并不是有效的US7ASCII编码,所以ORACLE OCI就转为了转省值3F3F(US7ASCII是单字节Oracle字符集,会认为“中”字是两个字符,因此为有两个3F) 这就是“??”号的由来。

000000900000000000000000000000C81DFF001C……………. 
000000A0696E7365727420696E746F2074312076insert.into.t1.v 
000000B0616C7565732028273F3F272901000000alues.(’??’)…. 
000000C001000000000000000000000000000000……………. 

我们再看看将客户端NLS_LANG设置为simplified chinese_china.zhs16cgb231280会发生什么

本文来源:1818IP

本文地址:https://www.1818ip.com/post/11189.html

免责声明:本文由用户上传,如有侵权请联系删除!

发表评论

必填

选填

选填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。