草庐IT

Oracle-修改字符集

小宝大人 2023-03-28 原文

字符集的概念

Oracle字符集是一个字节数据的符号集合,有大小之分,有相互的包容关系。Oracle支持国家语言的体系结构,允许你使用本地化语言来存储,处理,检索数据。它使数据库工具,错误消息,排序次序,日期,时间,货币,数字,和日历自动适应本地化语言和平台。

影响Oracle数据库字符集最重要的参数是NLS_LANG参数。格式:NLS_LANG =language_territory.charset

其中:Language 指定服务器消息的语言,territory 指定服务器的日期和数字格式,charset 指定字符集。如:AMERICAN_AMERICA、ZHS16GBK。从NLS_LANG的组成我们可以看出,真正影响数据库字符集的其实是第三部分。所以两个数据库之间的字符集只要第三部分一样就可以相互导入导出数据,前面影响的只是提示信息是中文还是英文。

Oracle的字符集有互相的包容关系。如us7ascii就是zhs16gbk的子集,从us7ascii到zhs16gbk不会有数据解释上的问题,不会有数据丢失。在所有的字符集中utf8应该是最大,因为它基于unicode,双字节保存字符(也因此在存储空间上占用更多)。

一旦数据库创建后,数据库的字符集理论上讲是不能改变的。字符集的转换是从子集到超集受支持,反之不行。如果两种字符集之间根本没有子集和超集的关系,那么字符集的转换是不受Oracle支持的。一般来说,除非万不得已,不建议修改Oracle数据库server端的字符集。特别说明,最常用的两种字符集ZHS16GBK和ZHS16CGB231280之间不存在子集和超集关系,因此理论上讲,这两种字符集之间的相互转换不受支持。

查询字符集

查询oracle server端的字符集

select userenv('language') from dual;

USERENV('LANGUAGE')
--------------------------------------------------------------------------------
AMERICAN_AMERICA.ZHS16GBK
select * from v$nls_parameters;

PARAMETER VALUE CON_ID
------------------------------ ---------------------------------------- ----------
NLS_LANGUAGE AMERICAN 1
NLS_TERRITORY AMERICA 1
NLS_CURRENCY $ 1
NLS_ISO_CURRENCY AMERICA 1
NLS_NUMERIC_CHARACTERS ., 1
NLS_CALENDAR GREGORIAN 1
NLS_DATE_FORMAT DD-MON-RR 1
NLS_DATE_LANGUAGE AMERICAN 1
NLS_CHARACTERSET ZHS16GBK 1
NLS_SORT BINARY 1
NLS_TIME_FORMAT HH.MI.SSXFF AM 1

PARAMETER VALUE CON_ID
------------------------------ ---------------------------------------- ----------
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM 1
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR 1
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR 1
NLS_DUAL_CURRENCY $ 1
NLS_NCHAR_CHARACTERSET AL16UTF16 1
NLS_COMP BINARY 1
NLS_LENGTH_SEMANTICS BYTE 1
NLS_NCHAR_CONV_EXCP FALSE 1

19 rows selected.

查询dmp文件的字符集

用Oracle的expdp工具导出的dmp文件也包含了字符集信息。如果dmp文件不大,比如只有几M或几十M,可以用UltraEdit打开(16进制方式)。如下图:

如果dmp文件很大,比如有2G以上(这也是最常见的情况),用文本编辑器打开很慢或者完全打不开,可以用以下命令(在Linux主机上):

hexdump -C ora_baoyw_file.dmp | more

16进制转换

> select to_char(nls_charset_id('ZHS16GBK'),'xxxx') from dual;

TO_CHAR(NLS_CHA
---------------
354

也可以不打开,用以下脚本:

cat ora_baoyw_file.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6

修改字符集

RAC-修改实例字符集

RAC环境下,修改字符集时,需要关闭全部节点。然后打开节点1,在节点1下操作即可。

SYS@b19c01> startup
ORACLE instance started.

Total System Global Area 2734682488 bytes
Fixed Size 9138552 bytes
Variable Size 553648128 bytes
Database Buffers 2164260864 bytes
Redo Buffers 7634944 bytes
Database mounted.
Database opened.
SYS@b19c01> select userenv('language') from dual;

USERENV('LANGUAGE')
----------------------------------------------------
AMERICAN_AMERICA.AL32UTF8

SYS@b19c01> show parameter cluster_database

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
cluster_database boolean TRUE
cluster_database_instances integer 2
SYS@b19c01> alter system set cluster_database=FALSE sid='*' scope=spfile;

System altered.

SYS@b19c01> show parameter cluster_database

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
cluster_database boolean TRUE
cluster_database_instances integer 2
SYS@b19c01> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SYS@b19c01>
SYS@b19c01> startup nomount
ORACLE instance started.

Total System Global Area 2734682488 bytes
Fixed Size 9138552 bytes
Variable Size 553648128 bytes
Database Buffers 2164260864 bytes
Redo Buffers 7634944 bytes
SYS@b19c01> alter database mount exclusive;

Database altered.

SYS@b19c01> alter system enable restricted session;

System altered.

SYS@b19c01> alter system set job_queue_processes=0;

System altered.

SYS@b19c01> alter system set aq_tm_processes=0;

System altered.

SYS@b19c01> alter database open;

Database altered.

SYS@b19c01> show parameter cluster_database

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
cluster_database boolean FALSE
cluster_database_instances integer 1
SYS@b19c01>
SYS@b19c01> alter database character set internal_use ZHS16GBK;

Database altered.

SYS@b19c01> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SYS@b19c01> startup
ORA-01102: cannot mount database in EXCLUSIVE mode
SYS@b19c01>
SYS@b19c01> startup
ORA-01102: cannot mount database in EXCLUSIVE mode
SYS@b19c01>
SYS@b19c01> startup
ORACLE instance started.

Total System Global Area 2734682488 bytes
Fixed Size 9138552 bytes
Variable Size 553648128 bytes
Database Buffers 2164260864 bytes
Redo Buffers 7634944 bytes
Database mounted.
Database opened.
SYS@b19c01>
SYS@b19c01> select userenv('language') from dual;

USERENV('LANGUAGE')
--------------------------------------------------------------------------------
AMERICAN_AMERICA.ZHS16GBK

SYS@b19c01> set linesize 200;
SYS@b19c01> col parameter for a30;
SYS@b19c01> col value for a40;
SYS@b19c01> select * from v$nls_parameters;

PARAMETER VALUE CON_ID
------------------------------ ---------------------------------------- ----------
NLS_LANGUAGE AMERICAN 1
NLS_TERRITORY AMERICA 1
NLS_CURRENCY $ 1
NLS_ISO_CURRENCY AMERICA 1
NLS_NUMERIC_CHARACTERS ., 1
NLS_CALENDAR GREGORIAN 1
NLS_DATE_FORMAT DD-MON-RR 1
NLS_DATE_LANGUAGE AMERICAN 1
NLS_CHARACTERSET ZHS16GBK 1
NLS_SORT BINARY 1
NLS_TIME_FORMAT HH.MI.SSXFF AM 1

PARAMETER VALUE CON_ID
------------------------------ ---------------------------------------- ----------
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM 1
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR 1
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR 1
NLS_DUAL_CURRENCY $ 1
NLS_NCHAR_CHARACTERSET AL16UTF16 1
NLS_COMP BINARY 1
NLS_LENGTH_SEMANTICS BYTE 1
NLS_NCHAR_CONV_EXCP FALSE 1

19 rows selected.

SYS@b19c01>
startup
##查询当前字符集
select userenv('language') from dual;
##设置参数cluster_database=FALSE
alter system set cluster_database=FALSE scope=spfile sid='*';
##关闭数据库
shutdown immediate
##启动数据库到nomount
startup nomount
##启动数据库到mount exclusive模式
alter database mount exclusive;
##启用受限会话
alter system enable restricted session;
##设置作业队列进程为0
alter system set job_queue_processes=0;
##设置aq_tm_processes=0 此参数监控队列消息的时间, 并控制处理具有指定延迟和过期属性的消息。
alter system set aq_tm_processes=0;
##打开数据库
alter database open;
##设置字符集 internal_use跳过子集与超集的检验修改字符集
alter database character set internal_use ZHS16GBK;
##恢复参数cluster_database=TRUE
alter system set cluster_database=TRUE sid='*' scope=spfile;
##恢复消息队列参数为默认值
alter system set job_queue_processes=1000;
alter system set aq_tm_processes=1;
##关闭
shutdown immediate
##启动
startup

####修改完成后,以下3个参数,改回原值
##在单机环境下 参数 cluster_database 不需要做修改。
##参数 cluster_database 如果为 FALSE,在集群环境下,只能启动一个节点
##否则会报错 ORA-01102: cannot mount database in EXCLUSIVE mode
alter system set cluster_database=TRUE sid='*' scope=spfile;
##以下两个参数关系到消息队列,也需修改为默认值
alter system set job_queue_processes=1000;
alter system set aq_tm_processes=1;

RAC-修改PDB字符集

SYS@b19c01> show pdbs

CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1 READ WRITE NO
4 PDB2 MOUNTED
SYS@b19c01> alter session set container=pdb1;

Session altered.

SYS@b19c01> select userenv('language') from dual;

USERENV('LANGUAGE')
----------------------------------------------------
AMERICAN_AMERICA.AL32UTF8

SYS@b19c01> alter pluggable database pdb1 close immediate;

Pluggable database altered.

SYS@b19c01> alter pluggable database pdb1 open read write restricted;

Pluggable database altered.

SYS@b19c01> select userenv('language') from dual;

USERENV('LANGUAGE')
----------------------------------------------------
AMERICAN_AMERICA.AL32UTF8

SYS@b19c01> alter database character set internal_use ZHS16GBK;
alter database character set internal_use ZHS16GBK
*
ERROR at line 1:
ORA-65025: Pluggable database PDB1 is not closed on all instances.


SYS@b19c01> alter database character set internal_use ZHS16GBK;

Database altered.

SYS@b19c01> alter pluggable database pdb1 close immediate;

Pluggable database altered.

SYS@b19c01> alter pluggable database pdb1 open;

Pluggable database altered.

SYS@b19c01> select userenv('language') from dual;

USERENV('LANGUAGE')
--------------------------------------------------------------------------------
AMERICAN_AMERICA.ZHS16GBK

SYS@b19c01> set linesize 200;
SYS@b19c01> col parameter for a30;
SYS@b19c01> col value for a40;
SYS@b19c01> select * from v$nls_parameters;

PARAMETER VALUE CON_ID
------------------------------ ---------------------------------------- ----------
NLS_LANGUAGE AMERICAN 3
NLS_TERRITORY AMERICA 3
NLS_CURRENCY $ 3
NLS_ISO_CURRENCY AMERICA 3
NLS_NUMERIC_CHARACTERS ., 3
NLS_CALENDAR GREGORIAN 3
NLS_DATE_FORMAT DD-MON-RR 3
NLS_DATE_LANGUAGE AMERICAN 3
NLS_CHARACTERSET ZHS16GBK 3
NLS_SORT BINARY 3
NLS_TIME_FORMAT HH.MI.SSXFF AM 3

PARAMETER VALUE CON_ID
------------------------------ ---------------------------------------- ----------
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM 3
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR 3
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR 3
NLS_DUAL_CURRENCY $ 3
NLS_NCHAR_CHARACTERSET AL16UTF16 3
NLS_COMP BINARY 3
NLS_LENGTH_SEMANTICS BYTE 3
NLS_NCHAR_CONV_EXCP FALSE 3

19 rows selected.

SYS@b19c01>
alter session set container=pdb1;
alter pluggable database pdb1 close immediate;
##打开 PDB 受限状态
alter pluggable database pdb1 open read write restricted;
##修改字符集
alter database character set internal_use ZHS16GBK;
alter pluggable database pdb1 close immediate;
alter pluggable database pdb1 open;
select userenv('language') from dual;

单机-修改字符集

startup mount
alter system enable restricted session;
alter system set job_queue_processes=0;
alter system set aq_tm_processes=0;
alter database open;
alter database character set zhs16gbk;
--ORA-12712: new character set must be a superset of old character set
--ORA-12712:新字符集必须为旧字符集的超集
alter database character set internal_use zhs16gbk;
--使用 internal_use 使oracle数据库绕过了子集与超集的校验.
shutdown immediate
startup

有关Oracle-修改字符集的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  4. ruby-on-rails - unicode 字符串的长度 - 2

    在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)

  5. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  6. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  7. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  8. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  9. ruby - 如何使用文字标量样式在 YAML 中转储字符串? - 2

    我有一大串格式化数据(例如JSON),我想使用Psychinruby​​同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解

  10. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

随机推荐