Oracle 11gR2修改服务器端字符集

本文详细介绍了如何修改Oracle 11gR2服务器端的字符集,包括字符集编码知识、修改步骤、客户端设置及sql脚本执行时的字符集测试。重点讨论了NLS_CHARACTERSET和NLS_NCHAR_CHARACTERSET的区别,并提供了Windows下修改cmd字符集的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.字符集编码知识


查询字符集编码:

SQL>  select userenv('language') from dual; 

或者 select * from V$NLS_PARAMETERS;

或者 select * from nls_database_parameters where parameter like 'NLS%CHARACTERSET';


USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK

环境变量nls_lang便是由这三部分组成:

1. NLS_LANGUAGE

2. NLS_TERRITORY

3. NLS_CHARACTERSET

组成如下:NLS_LANG = language_territory.charset

即语言、地域和字符集,每个成分控制了 NLS 子集的特性。其中:
Language: 指定服务器消息的语言, 影响提示信息是中文还是英文
Territory: 指定服务器的日期和数字格式

Charset:指定字符集。

真正影响数据库的是第三部分,因此,我们将Charset修改为常用的AL32UTF8


二. 修改Oracle服务器端的字符集


SQL> shutdown immediate
SQL> startup nomount
SQL> alter database mount exclusive;  --装载数据为专用的高级模式;
SQL> alter system enable restricted session; --启用受限制的session模式
SQL> alter system set job_queue_processes=0; --'maximum number of job queue slave processes' 设置工作队列的最大进程数为0
SQL> alter system set aq_tm_processes=0;
SQL> alter database open;
SQL> alter database character set AL32UTF8; --新的字符集必须支持旧的字符集(旧字符集的超集),
报错:ORA-12712: new character set must be a superset of old character set,
SQL> shutdown immediate
SQL> startup

因为没有执行成功,所以再次查询依然是 ZHS16GBK

SQL>  select userenv('language') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK

于是重新关闭数据库,重新执行:
SQL>shutdown immediate;
等了好长时间没有反映,于是重新打开终端,然后重新进入数据库,报错!
ERROR:
ORA-28056: Writing audit records to Windows Event Log failed
ORA-28056: Writing audit records to Windows Event Log failed
查询alert_log后发现:
OSD-00001: 附加错误信息
O/S-Error: (OS 1502)
事件日志文件已满。
原来是系统日志写满了,需要清除后在登录,于是按照 http://jingyan.baidu.com/article/ce436649f198503772afd355.html将系统日志清除,正常重启。
更详细的解决方案如下:

Cause
The Event Viewer log is full and not able to log any more events.

Justified by unpublished Bug 6823281 ORA-28056 WRITING AUDIT RECORDS TO WINDOWS EVENT LOG FAILED

which was closed as not a bug.

Solution
Try doing the following using Windows Event Viewer:

To open Event Viewer, click Start, click Control Panel, 
click Performance and Maintenance, click Administrative Tools, 
and then double-click Event Viewer.

You must be logged on as an administrator or a member of the 
Administrators group to free an event log.

1) When a log is full, it stops recording new events. Clearing the log 
is one way to free the log and start recording new events.

2) You can also free a log and start recording new events by overwriting 
old events. To overwrite events, on the Action menu, click Properties, 
and then click Overwrite events as needed. This ensures that all new 
events are written to the log, even when the log is full.

3) You can also start logging new events by increasing the maximum 
log size. To increase the log size, on the Action menu, click Properties, 
and then increase the Maximum log size. 
References


言归正传,刚才ORA-12712错误是因为改后字符集必须是现字符集的超子集可以使用INTERNAL_USE 跳过超子集检测,于是将
SQL> alter database character set AL32UTF8; 
改为:
SQL> alter database character set  INTERNAL_USE  AL32UTF8; 

SQL> select userenv('language') from dual;

USERENV('LANGUAGE')
-------------------------------------------------------------------------------
SIMPLIFIED CHINESE_CHINA.AL32UTF8

可以看到已经更改成功!如果此时执行命令时出现乱码可能是因为本机的NLS_LANG参数和Oracle服务器不一致。


三. 客户端关于Oracle的字符集编码设置


客户端与服务器端字符集不一致时可能导致cmd或者shell显示乱码:

Windows:
# 常用中文字符集
set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK(仅在此cmd窗口立即生效)
# 常用unicode字符集
set NLS_LANG=american_america.AL32UTF8
可以通过修改注册表键值永久设置
HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/KEY_OraDb11g_home1/NLS_LANG(任何窗口生效,但是需要重启系统生效)

#通过属性-高级系统设置-环境变量加入

NLS_LANG=american_america.AL32UTF8环境变量(此环境变量优先级高于注册表环境变量)


Unix:
# 常用unicode字符集
export NLS_LANG=american_america.AL32UTF8
# 常用中文字符集
export NLS_LANG="Simplified Chinese_china".ZHS16GBK
可以编辑 bash_profile 文件进行永久设置
vi .bash_profile
NLS_LANG="Simplified Chinese_china".ZHS16GBK export NLS_LANG
# 使 bash_profile 设置生效
source .bash_profile



四. sql脚本导入Oralce服务器执行时各种字符集的测试


windows下Oracle11gR2服务器端字符集编码为 CHINESE_CHINA.ZHS16GBK,NLS_LANG变量编码为CHINESE_CHINA.ZHS16GBK,sql脚本编码为UTF8编码。以此为测试环境,测试sql脚本编码和服务器端字符集编码各种情况下的结果:

执行结果


结果一. 在windows下装Oracle服务器端字符集为 CHINESE_CHINA.ZHS16GBK,装载UTF8编码的sql脚本文件,在数据库中查询出来的中文是乱码;将UTF8编码的sql脚本文件复制出来后再粘贴至新建的sql文件中(可能已经是CHINESE_CHINA.ZHS16GBK编码),然后重新执行插入后没有乱码现象。

结果二.接着结果一。强行将Oracle服务器端字符集由CHINESE_CHINA.ZHS16GBK改为CHINESE_CHINA.AL32UTF8后,原来查询不是乱码的中文出现  ERROR:ORA-29275: 部分多字节字符,不是乱码这么简单了

结果三。接着结果二,再强行将Oracle服务器端字符集由改回原来的CHINESE_CHINA.ZHS16GBK后,查询原中文恢复正常,没有出现乱码。

结果四。接着结果三。删除后sql脚本执行结果后,重新执行UTF8编码的脚本(Oracle服务器端字符集为CHINESE_CHINA.AL32UTF8,没有特意设置系统的NLS_LANG变量),查询出来的中文是乱码。(后来分析可能是UTF8编码的脚本有问题);

结果五。接着结果四。删除后重新执行UTF8编码的脚本(Oracle服务器端字符集为CHINESE_CHINA.AL32UTF8,设置系统的NLS_LANG变量为CHINESE_CHINA.AL32UTF8),查询出来的中文仍然是乱码。但是在终端里自己写插入语句插入中文再查询不是乱码(是不是显示时不是UTF8编码?)。

结果六。接着结果五。再强行将Oracle服务器端字符集改为CHINESE_CHINA.AL32UTF8后,查询仍然是乱码

对结果的分析


如果是UTF8的sql脚本插入字符集为CHINESE_CHINA.AL32UTF8的数据库应该没有问题的,也就是不会出现乱码,出现乱码的原因如下:

1.UTF8编码的sql脚本有问题,因为在执行sql脚本时,部分语句出现 ERROR:ORA-01756: 引号内的字符串没有正确结束,但经过仔细检查没有任何语法错误,由此推测sql脚本不是真正的UTF8编码,在用UltraEdit再重新生成UTF8编码后(UltraEdit:文件->转换)就果然没有问题了。

2.UTF8的脚本插入字符集为CHINESE_CHINA.AL32UTF8的数据库应该没有问题,也就是存储的中文数据是正确的。windows显示错误的原因肯能是cmd终端的编码不是UTF8,使用http://blog.itpub.net/25744374/viewspace-753227/
(1. chcp 65001  2.属性->字体->Lucida Console) 将cmd字符集更改后就可以正常显示中文了。

3. 在修改系统的NLS_LANG变量为CHINESE_CHINA.AL32UTF8时,必须要关闭所有cmd窗口,然后再重新开才会生效。

4.如果Oracle服务器字符集由GBK 改为UTF8后,存储的数据不能自动改变其编码,还是GBK的编码,则显示时有可能出现乱码。(没有乱码的情况:当客户端编码为UTF8,操作系统编码(cmd窗口或Shell终端)为GBK时。因为Oracle中存储的编码格式是GBK的,而且客户端编码=服务器端编码=UTF8,所以在取出时不需要转换编码,而操作系统编码是GBK,显示GBK编码当然没有问题了)。


补充:


NLS_CHARACTERSET与NLS_NCHAR_CHARACTERSET的区别


NLS_CHARACTERSET是数据库字符集,NLS_NCHAR_CHARACTERSET是国家字符集
ORACLE中有两大类字符型数据,VARCHAR2是按照数据库字符集来存储数据。而NVARCHAR2是按照国家字符集存储数据的。同样,CHAR和NCHAR也一样,一是数据库字符符,一是国家字符集。
字符集不同,二进制码的组合就不同。
比如有一串二进制信息:1101,0110,1101,0000,1011,1001,1111,1010,按照16位双字节GBK字符集理解,可以代表“中国”两个字。如果单字节的字符集,这一串二进制代表ASC码为214、208、185、250的四个怪字符。
这就是字符集的作用,就是以什么样的形式理解信息。

The NLS_CHARACTERSET is used for CHAR, VARCHAR2, LONG and CLOB columns;
The NLS_NCHAR_CHARACTERSET is used for NCHAR, NVARCHAR2 and NCLOB columns.
From 9i onwards the NLS_NCHAR_CHARACTERSET can have only 2 values: UTF8 or AL16UTF16 who are Unicode charactersets


注:我的例子中“中国”的二进制形式来自dump('中国',16)。


Windows修改cmd字符集 


http://blog.itpub.net/25744374/viewspace-753227/


oracle不同系统之间时间转换


http://www.2cto.com/database/201302/191460.html


 参考:

http://blog.chinaunix.net/uid-25492475-id-3140218.html

http://www.eygle.com/archives/2004/09/nls_character_set_01.html

http://blog.youkuaiyun.com/wzy0623/article/details/1683337

http://blog.sina.com.cn/s/blog_95c27c530101ap58.html

http://bbs.51cto.com/thread-1017691-1.html

http://blog.chinaunix.net/uid-21125022-id-4195664.html
http://blog.youkuaiyun.com/ding43930053/article/details/42460693
http://www.cnblogs.com/lanston/p/3755978.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值