oracle的NLS_CHARACTERSET是ora12737 zhs16gbkK jsp是gb2312 我要怎么弄才能保证汉子录入到oracle里不是乱码

后使用快捷导航没有帐号?
只需一步,快速开始
查看: 521|回复: 0
UID帖子阅读权限20精华贴数技术排名14853 专家积分4 社区排名2708818 技术积分196 社区积分0 注册时间
精华贴数专家积分4 技术积分196 社区积分0 注册时间
论坛徽章:2
最近碰到个很妖的问题:一个9i for hpux的库,在没有重启的情况下,V$NLS_PARAMETERS中NLS_NCHAR_CHARACTERSET居然变成ZHS16GBK,测试环境怎么都模拟不去出来,郁闷。。。
SQL& select * from database_
PROPERTY_NAME& && && && && && &PROPERTY_VALUE& && && && && && &&&DESCRIPTION
------------------------------ --------------------------------- ---------------------------------
NLS_CHARACTERSET& && && && && &ZHS16GBK& && && && && && && && &&&Character set
NLS_NCHAR_CHARACTERSET& && && &AL16UTF16& && && && && && && && & NCHAR Character set
SQL& select * from v$nls_
PARAMETER& && && && && && && && && && && && && && && && && && &&&VALUE
---------------------------------------------------------------- ----------------------------------------------------------------
NLS_CHARACTERSET& && && && && && && && && && && && && && && && & ZHS16GBK
NLS_NCHAR_CHARACTERSET& && && && && && && && && && && && && && & ZHS16GBK&&&------
谁能解释下?
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp
:&&nbsp&&nbsp&&nbsp&&nbsp
itpub.net All Right Reserved. 北京皓辰网域网络信息技术有限公司版权所有    
 北京市公安局海淀分局网监中心备案编号: 广播电视节目制作经营许可证:编号(京)字第1149号oracle支持GB2312么?
[问题点数:20分,结帖人xuelianlee]
oracle支持GB2312么?
[问题点数:20分,结帖人xuelianlee]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
本帖子已过去太久远了,不再提供回复功能。PHP has encountered an Access Violation at 7C94BB52oracle的NLS_CHARACTERSET是ZHS16GBK jsp是gb2312 我要怎么弄才能保证汉子录入到oracle里不是乱码_百度知道
oracle的NLS_CHARACTERSET是ZHS16GBK jsp是gb2312 我要怎么弄才能保证汉子录入到oracle里不是乱码
我是新手 oracle的NLS_CHARACTERSET是ZHS16GBK jsp是gb2312 我要怎么弄才能保证汉字插入到oracle里不是乱码 现在oracle的字符集我没有权限弄
oracle的字符集也没那么容易调整的,除非重新建一个库指定好字符集是GB2312,尝试从JSP上改吧
其他类似问题
nls的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁oracle的字符集设置与乱码 - CSDN博客
字符集问题一直叫人头疼,究其原因还是不能完全明白其运作原理。
在整个运行环节中,字符集在3个环节中发挥作用:
1.软件在操作系统上运作时的对用户的显示,此时采用操作系统定义的字符集进行显示。我们在系统I/O编程的时候经常要指定字符集,C#中的Text.Encoding=Encoding.Default实际上就是告诉编译器,文本使用系统定义的默认字符集进行编码。sqlplus也是运行在操作系统上的软件,当然要使用系统所指定的字符集对外显示内容。
2.数据向oracle服务端传送前的通告。也就是sqlplus告诉服务器现在使用的字符集是什么。
3.数据流到达服务器后,按照服务器所使用的字符集自动翻译客户端的数据,然后存储进系统。
在客户端sqlplus和服务端传送数据,数据会按照服务端字符集进行翻译,这个过程是自动完成的不需要人工干预。任何时候,oracle服务端总是按照自己的字符集设置来存取数据,客户端要想正确显示从服务端读取到的数据,也需要按照本地的字符集设置进行翻译,这个过程也是自动的。
服务器端需要采用合适的字符集进行数据存储,这个很容易理解,ASCII字符集没办法用来存储中文汉字,因为它根本没有描述汉字所需要的编码空间。
问题常常存在于客户端与服务端通讯的过程中,sqlplus作为运行在操作系统上的软件,无论是显示还是通讯,必然使用操作系统所使用的字符集设置。无论sqlplus设置的字符集,作用只有一个,那就是通告服务器端,为相互之间的字符集翻译做准备。
客户端的字符集设置是在NLS_LANG环境变量中设置的,客户读端的字符集可以和oracle客户端设置得不一样(本来人家就是自动翻译的),但是客户端字符集一定要和操作系统设置的字符集相匹配!
考虑一下,sqlplus使用的是操作系统的字符集定义在显示和发送数据(架设是TYPE_A),却告诉oracle服务器自己使用的字符集是TYPE_B,oracle服务器会怎么办?它会将客户端发送过来的TYPE_A数据当作TYPE_B字符集格式用自身的TYPE_C字符集进行翻译,然后再存储进系统,这就形成了乱码。反向的过程类似,Oracle服务器发出的数据格式没有疑问是TYPE_C,但是客户端软件认为自己使用的编码是TYPE_B并进行了翻译,交给操作系统用TYPE_A字符集总的字符/编码映射关系进行翻译显示,最终导致了无法正确显示。
一个现实的例子:RHEL5.8操作系统安装了中文支持包以后,所有的语言环境都被设置成了zh_CN.UTF-8(通过LANG环境变量可知,也可通过locale命令查到),数据库服务器所使用的字符集为ZHS16GBK,很明显,这两者不一致,sqlplus在没有设置NLS_LANG环境变量时,与数据库保持一致,此时,从服务端取得的数据不需要翻译,被sqlplus读取并用zh_CN.UTF-8的字符/编码映射关系进行翻译显示,所有的汉字变成了“?”。
根据上面的分析,要解决这一问题,要把sqlplus的字符集设置成和操作系统一致即可,操作系统设置的是zh_CN.UTF-8,但在.bash_profile里面还不能直接将NLS_LANG设置为zh_CN.UTF-8,因为这个zh_CN.UTF8是字符集的localeID而不是字符集的名称,真正的名称叫SIMPLIFIEDCHINESE_CHINA.AL32UTF8,如果设置成zh_CN.UTF8,oracle会报ORA-12705: Cannotaccess NLS data files or invalid
environmentspecified错误。在.bash_profile里面加入NLS_LANG=&SIMPLIFIEDCHINESE_CHINA.AL32UTF8&; export NLS_LANG问题就解决了。
下表是locale ID与字符集名称的对应关系:
English (American)
en_US.UTF-8
AMERICAN_AMERICA.AL32UTF8
English (American)
en_US.ISO-8859-1
AMERICAN_AMERICA.WE8ISO8859P1
English (American)
en_US.ISO-8859-15
AMERICAN_AMERICA.WE8ISO8859P15
English (Australian)
en_AU.UTF-8
ENGLISH_AUSTRALIA.AL32UTF8
English (Australian)
en_AU.ISO-8859-1
ENGLISH_AUSTRALIA.WE8ISO8859P1
English (Australian)
en_AU.ISO-8859-15
ENGLISH_AUSTRALIA.WE8ISO8859P15
English (British)
en_GB.UTF-8
ENGLISH_UNITED KINGDOM.AL32UTF8
English (British)
en_GB.ISO-8859-1
ENGLISH_UNITED KINGDOM.WE8ISO8859P1
English (British)
en_GB.ISO-8859-15
ENGLISH_UNITEDKINGDOM.WE8ISO8859P15
English (Ireland)
en_IE.UTF-8
ENGLISH_IRELAND.AL32UTF8
English (Ireland)
en_IE.ISO-8859-1
ENGLISH_IRELAND.WE8ISO8859P1
English (Ireland)
en_IE.ISO-8859-15
ENGLISH_IRELAND.WE8ISO8859P15
de_DE.UTF-8
GERMAN_GERMANY.AL32UTF8
de_DE.ISO-8859-1
GERMAN_GERMANY.WE8ISO8859P1
de_DE.ISO-8859-15
GERMAN_GERMANY.WE8ISO8859P15
fr_FR.UTF-8
FRENCH_FRANCE.AL32UTF8
fr_FR.ISO-8859-1
FRENCH_FRANCE.WE8ISO8859P1
fr_FR.ISO-8859-15
FRENCH_FRANCE.WE8ISO8859P15
it_IT.UTF-8
ITALIAN_ITALY.AL32UTF8
it_IT.ISO-8859-1
ITALIAN_ITALY.WE8ISO8859P1
it_IT.ISO-8859-15
ITALIAN_ITALY.WE8ISO8859P15
es_ES.UTF-8
SPANISH_SPAIN.AL32UTF8
es_ES.ISO-8859-1
SPANISH_SPAIN.WE8ISO8859P1
es_ES.ISO-8859-15
SPANISH_SPAIN.WE8ISO8859P15
Spanish (Mexico)
es_MX.UTF-8
MEXICAN SPANISH_MEXICO.AL32UTF8
Spanish (Mexico)
es_MX.ISO-8859-1
MEXICAN SPANISH_MEXICO.WE8ISO8859P1
Spanish (Mexico)
es_MX.ISO-8859-15
MEXICANSPANISH_MEXICO.WE8ISO8859P15
Portuguese (Brazilian)
pt_BR.UTF-8
BRAZILIANPORTUGUESE_BRAZIL.AL32UTF8
Portuguese (Brazilian)
pt_BR.ISO-8859-1
BRAZILIANPORTUGUESE_BRAZIL.WE8ISO8859P1
Portuguese (Brazilian)
pt_BR.ISO-8859-15
BRAZILIANPORTUGUESE_BRAZIL.WE8ISO8859P15
ja_JP.EUC-JP
JAPANESE_JAPAN.JA16EUC
ja_JP.UTF-8
JAPANESE_JAPAN.AL32UTF8
ko_KR.EUC-KR
KOREAN_KOREA.KO16KSC5601
ko_KR.UTF-8
KOREAN_KOREA.AL32UTF8
Chinese (simplified)
zh_CN.GB18030
SIMPLIFIEDCHINESE_CHINA.ZHS32GB18030
Chinese (simplified)
zh_CN.UTF-8
SIMPLIFIED CHINESE_CHINA.AL32UTF8
Chinese (traditional)
zh_TW.BIG5
TRADITIONALCHINESE_TAIWAN.ZHT16BIG5
Chinese (traditional)
zh_TW.UTF-8
TRADITIONAL CHINESE_TAIWAN
步骤可以归纳为:1.找到操作系统使用的字符集,并按上表找到对应的字符集名称。2.修改客户端软件的字符集NLS_LANG环境变量设置。
不同平台的一些细节:
Windows( 如简体系统为:ZHS16GBK,繁体系统为:MSWIN950 )
1、设置session变量
# 常用中文字符集
set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
# 常用unicode字符集
set NLS_LANG=american_america.AL32UTF8
2、可以通过修改注册表键值永久设置
HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/HOMExx/NLS_LANG
3、设置环境变量
NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
NLS_LANG=american_america.AL32UTF8
Unix/Linus:
1、设置session变量
# 常用unicode字符集
export NLS_LANG=american_america.AL32UTF8
# 常用中文字符集
export NLS_LANG=&Simplified Chinese_china&.ZHS16GBK
3、设置环境变量
可以编辑 bash_profile文件进行永久设置
# vi .bash_profile
NLS_LANG=&Simplified Chinese_china&.ZHS16GBK
export NLS_LANG
# 使 bash_profile 设置生效
source .bash_profile
1、查看sqlplus客户编码:
2、查看系统编码:
3、查看数据库字符集,执行如下查询:
select userenv('language')
作者:hcling97&&&&
转载请注明出处&
------------------------------------------------------------------------------------------------------------------------
万国码(Unicode):包含了几乎人类所有可用的字符,每年还在不断的增加,可以看作是一种通用的字符集。它将全世界所有的字符统一化,统一编码,不会再出现字符不兼容和字符转换的问题。它有以下三种编码方式:
UTF-32编码:固定使用4个字节来表示一个字符,存在空间利用效率的问题。
UTF-16编码:对相对常用的60000余个字符使用两个字节进行编码,其余的使用4字节。
UTF- 8编码:兼容ASCII编码;拉丁文、希腊文等使用两个字节;包括汉字在内的其它常用字符使用三个字节;剩下的极少使用的字符使用四个字节。
Oracle字符集基本原理
在搞懂Oracle字符集基本原理之前,一定要先分清以下三个概念:
1. Oracle数据库服务器字符集:即Oracle以哪种字符编码存储字符,可以通过以下语句查出数据库字符集的设置。
SQL&&select&*&from&v$nls_parameters&where&parameter='NLS_CHARACTERSET';&&&&PARAMETER&&&&&&&&&&&&&&&&&&&&&&VALUE&&&&NLS_CHARACTERSET&&&&&&&&&&&&&&&AL32UTF8&&
2. 客户端操作系统字符集:即客户端操作系统以哪种字符编码存储字符。
如果是Windows,可以使用chcp命令获得代码页(code page):
C:\Users\xianzhu&chcp&&Active&code&page:&936&&
根据该代码页,到微软的官方文档《》找到其对应的字符集。
如果是Linux,字符集在/etc/sysconfig/i18n设置:
LANG=&zh_CN.GB2312&&(指定当前操作系统的字符集)&&&SUPPORTED=&zh_CN.GB2312&(指定当前操作系统支持的字符集)&&&SYSFONT=&lat0-sun16&(指定当前操作系统的字体)&&
3. 客户端NLS_LANG参数:该参数用于向Oracle指示客户端操作系统的字符集。
有了以上3个基本概念之后,我来阐述一下Oracle字符集转换的基本原则:
设置客户端的NLS_LANG为客户端操作系统的字符集如果数据库字符集等于NLS_LANG,数据库和客户端传输字符时不作任何转换如果它们俩不等,则需要在不同字符集间转换,只有客户端操作系统字符集是数据库字符集子集的基础上才能正确转换,否则会出现乱码。
几种常见情况分析
下面先看一个例子,再透过现象看本质,我们会针对这个例子进行分析。
该例子如下:
1.&数据库字符集为Unicode(UTF-8编码)&&我们的数据库版本是10.2.0.4.0,数据库字符集是:&&SQL&&select&*&from&v$nls_parameters&where&parameter='NLS_CHARACTERSET';&&&&PARAMETER&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&VALUE&&&&NLS_CHARACTERSET&&&&&&&&&&&&&&&AL32UTF8&&&&2.&客户端操作系统字符集为代码页936(字符集为ZHS16GBK)&&可以使用chcp获得windows的代码页(code&page)&&C:\Documents&and&Settings\a105024\Desktop&chcp&&Active&code&page:&936&&&&3.&创建测试表&&SQL&&create&table&test(id&number,var&varchar2(30));&&&&Table&created.&&&&4.&插入数据&&这里在同一个操作系统启动两个session,session1的NLS_LANG设为和数据库字符集一样(即AL32UTF8):&&C:\Documents&and&Settings\a105024\Desktop&set&nls_lang=Simplified&Chinese_China.AL32UTF8&&连接数据库并插入一条数据:&&Session_1&insert&into&test&values(1,'中国');&&&&1&row&created.&&&&Session_1&commit;&&&&Commit&complete.&&&&session2的NLS_LANG设为和客户端操作系统一样(即ZHS16GBK):&&C:\Documents&and&Settings\a105024\Desktop&set&nls_lang=Simplified&Chinese_China.ZHS16GBK&&连接数据库并插入一条数据:&&Session_2&insert&into&test&values(2,'中国');&&&&1&row&created.&&&&Session_2&commit;&&&&Commit&complete.&&&&5.&执行查询&&在session&1上执行查询:&&Session_1&select&*&from&&&&&&&&&&&&&ID&VAR&&&&&&&&&&&&&1&中国&&&&&&&&&&&2&涓&&&浗&&在session&2上执行查询:&&Session_2&select&*&from&&&&&&&&&&&&&ID&VAR&&&&&&&&&&&&&1&???&&&&&&&&&&&2&中国&&
上面例子看起来很诡异,session1和2都能正常显示自己插入的字符串,又都不能正常显示对方插入的字符串。为了弄清楚,我们首先得知道数据库里对这两个字符串是怎么存储的。我们可以使用dump函数获得字符在数据库的编码:
SQL&&select&id,dump(var,1016)&from&&&ID&DUMP(VAR,1016)&&&&&1&Typ=1&Len=4&CharacterSet=AL32UTF8:&d6,d0,b9,fa&&&2&Typ=1&Len=6&CharacterSet=AL32UTF8:&e4,b8,ad,e5,9b,bd&&
根据AL32UTF8的编码,“中国”两字的正确编码为(都为3个字节):
中--e4,b8,ad
国--e5,9b,bd
因此session 1插入的字符串在数据库中的编码是错误的,session 2正确。这也是为什么一定要设置NLS_LANG为客户端操作系统的字符集。
但是根据上面实验我们可以知道,数据库中存储正确,并不代表客户端能正常显示;同样地,即时数据库没有正确存储,有时候客户端也能够正常显示,这又是为什么呢?别急,请听我慢慢道来:
场景1:session 1插入,session 1查询,在数据库中存储错误,但显示正确。
插入过程:
”中国“两字在客户端操作系统字符集ZHS16GBK中的编码是”d6,d0,b9,fa&,由于NLS_LANG和数据库字符集相同,数据库端对客户端传过来的字符编码不进行任何转换直接存入数据库,因此数据库中存储的编码也是“d6,d0,b9,fa”,
读取过程:
数据库端读取的编码是“d6,d0,b9,fa”,由于NLS_LANG和数据库字符集相同,客户端对数据库端传过来的字符编码不进行任何转换直接显示,编码”d6,d0,b9,fa“在客户端操作系统字符集ZHS16GBK对应的汉字为“中国”。
从以上分析可知,虽然读取时正确的,但那是因为负负得正,实际上数据库中存储是错误的,因此要特别小心这种情况,在生成库中要避免。其实只要对它进行length操作就能轻易揭开它的假面具:
Session_1&select&length(var)&from&test&where&id=1;&&&&LENGTH(VAR)&&&&&&&&&&&&&&3&&
得出的长度居然为3!实际的长度只是2,这会带来很多麻烦。
场景2:session 1插入,session 2查询,在数据库中存储错误,显示也错误。
插入过程和场景1一样,这里就不再累述。
读取过程:
数据库端读取的编码是“d6,d0,b9,fa”,由于NLS_LANG和数据库字符集不同,客户端对数据库端传过来的字符编码进行转换,数据库端字符集AL32UTF8里编为“d6,d0,b9,fa”无法在客户端操作系统字符集ZHS16GBK里找到对应的编码,所以只好用?代替。
场景3:session 2插入,session 1查询,在数据库中存储正确,但显示错误。
插入过程:
”中国“两字在客户端操作系统字符集ZHS16GBK中的编码是”d6,d0,b9,fa&,由于NLS_LANG和数据库字符集不同,Oracle会进行字符编码转换,也就是将字符集ZHS16GBK里“中国”的编码“d6,d0,b9,fa&转换为字符集&AL32UTF8&里”中国“的编码”e4,b8,ad,e5,9b,bd“。
读取过程:
数据库端读取的编码是”e4,b8,ad,e5,9b,bd“,由于NLS_LANG和数据库字符集相同,客户端对数据库端传过来的字符编码不进行任何转换直接显示,编码”e4,b8,ad,e5,9b,bd“在客户端操作系统字符集ZHS16GBK对应的汉字为“涓 & 浗”(原本2个字符,现在变成了3个字符,因为ZHS16GBK的汉字以2个字节编码)。
场景4:session 2插入,session 2查询,在数据库中存储正确,显示也正确。
插入过程和场景3类似。
读取过程:
数据库端读取的编码是”e4,b8,ad,e5,9b,bd“,由于NLS_LANG和数据库字符集不同,客户端对数据库端传过来的字符编码进行转换,数据库端字符集AL32UTF8里”中国“两字的编码”e4,b8,ad,e5,9b,bd“转换成客户端操作系统字符集ZHS16GBK里“中国”两字的编码“d6,d0,b9,fa&,并正常显示。
这种情况虽然经过了两次转换,都确实最正确、最推荐的方式。
附录:Oracle 字符集超集和子集的对应关系可查看:/docs/cd/B19306_01/server.102/b14225/applocaledata.htm#sthref1988
结论:NLS_LANG只和客户端操作系统的字符集相关,如果客户端操作系统的字符集和数据库字符集间无法正确转换,则应该首先改变客户端终端的字符集,而不是简单地把NLS_LANG设为和数据库字符集一样。
来源:http://blog.csdn.net/dbanote/article/details/9158367,作者:朱显杰
相关阅读:,}

我要回帖

更多关于 oracle nls 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信