适用于:
Oracle Database – Enterprise Edition – 版本 8.1.7.4 和更高版本
Oracle Database – Standard Edition – 版本 8.1.7.4 和更高版本
本文档所含信息适用于所有平台
用途
本文章概述了更改数据库字符集或在具有不同 NLS_CHARACTERSET 的数据库之间导出/导入前进行检查的方法。
当前的 NLS_CHARACTERSET 在 NLS_DATABASE_PARAMETERS 中可以看到。
select value from NLS_DATABASE_PARAMETERS where parameter=’NLS_CHARACTERSET’;
NLS_CHARACTERSET(“字符集”)定义了“普通”的 CHAR, VARCHAR2, LONG 以及 CLOB 字段的编码。
NLS_NCHAR_CHARACTERSET(“国家字符集”)定义了 NCHAR, NVARCHAR2 以及 NCLOB 字段的编码。从 9i 以后都是 Unicode 编码。如果没有使用 NCHAR, NVARCHAR2 以及 NCLOB 字段,那么 NLS_NCHAR_CHARACTERSET 的设置不会被使用或者说不相关。详见 Note 276914.1 The National Character Set in Oracle 9i , 10g and 11g
这是 Oracle Application 唯一支持的方法。如果您有任何疑问,请开一个 Oracle Applications SR 以寻求帮助。
适用范围
尝试更改 NLS_CHARACTERSET 的所有用户。
详细信息
A) 数据库字符集 (NLS_CHARACTERSET)
Oracle 数据库的 NLS_CHARACTERSET 定义了数据库中哪些字符可以存储在 CHAR、VARCHAR2、LONG 和 CLOB 数据类型中。字符集不定义语言,而是定义字符的特定范围。任何语言,只要它使用包含在该字符集中的字符,即可存储在数据库中。
一个使用 NLS_CHARACTERSET 为 WE8MSWIN1252 并且 NLS_LANGUAGE/NLS_TERRITORYJAPANESE 为 JAPAN 的数据库是不能存储日文的,因为 WE8MSWIN1252 中不包含日文字符的定义。
一个使用 NLS_CHARACTERSET 为 AL32UTF8 并且 NLS_LANGUAGE/NLS_TERRITORY 为 AMERICAN AMERICA 的数据库能存储日文 (或者从某种意义上说任何世界上其它的语言).
如果您准备修改数据库的字符集,并且当前使用的某些字符在新的字符集中没有定义,或者当前字符集的设置是不正确的,那么在字符集修改之后就可能发生数据丢失。
在更改字符集前,应始终使用 Character Set Scanner (Csscan) 检查是否存在这种情况。
使用导出/导入操作或 Expdp/Impdp 时也一样。
Note 458122.1 Installing and Configuring Csscan in 8i and 9i (Database Character Set Scanner)
Note 745809.1 Installing and configuring Csscan in 10g and 11g (Database Character Set Scanner)
Note 444701.1 Csscan output explained
如果将二进制数据作为 CHAR、VARCHAR2、LONG 或 CLOB 数据类型存储/处理,则可能会丢失数据,特别是在使用 AL32UTF8 数据库时(即使没有使用导出/导入操作)。或者,可能会出现 ORA-29275 或ORA-600 [kole_t2u], [34] 等错误。
请参阅 Note 1297507.1 Problems with (Importing) Encrypted Data After Character Set Change Using Other NLS_CHARACTERSET Database or Upgrading the (client) Oracle Version
B) 选择新数据库字符集
对于大多数客户,Unicode 字符集 (AL32UTF8) 是最好的选择。
使用AL32UTF8字符集的数据库,你可以存储/查询世界上所有的语言
请参阅 Note 333489.1 Choosing a database character set means choosing Unicode 以及 Note 1051824.6 What languages are supported in an Unicode (UTF8/AL32UTF8) database?
需要注意的是,在选择 Unicode(AL32UTF8) 数据库前,您需要确认应用程序是否支持。这个不是 Oracle 技术支持能检查或确认的。
请检查对应的应用程序文档,或咨询应用程序提供商及支持团队,以确认应用程序同 AL32UTF8 或 UTF8 的认证关系。我们强烈建议这么做。
不需要特意安装Unicode或其它字符集,因为所有Oracle的字符集包括Unicode,都已经默认安装了.
人们经常会有一个错误的认识,认为简单的使用NCHAR, NVARCHAR2 和 NCLOB就可以让应用程序变得Unicode化,并且比改变NLS_CHARACTERSET花费的工作更少.
但是一般的N-类型在编程语言以及应用的角度上的支持是很差的.为了使用N-类型,应用程序需要显式的支持.
所以Oracle一般建议使用NLS_CHARACTERSET, CHAR, VARCHAR2 , LONG 和 CLOB 这样的数据类型,而不是N-类型的数据类型.
对于非 Unicode 字符集,最佳选择是 xx8MSWIN125x 字符集,即使数据库自身在 Unix 平台上运行。原因很简单:大多数客户端都是基于 Windows 系统的,因此最适合数据库的非 Unicode 字符集是可以存储这些客户端能够识别的所有字符的字符集,即 xx8MSWIN125x 字符集:
EE8MSWIN1250 , CL8MSWIN1251, WE8MSWIN1252, EL8MSWIN1253 ,TR8MSWIN1254, IW8MSWIN1255, AR8MSWIN1256, BLT8MSWIN1257。
对于亚洲语言推荐的字符集是 VN8MSWIN1258, TH8TISASCII, JA16SJIS , KO16MSWIN949, ZHS16GBK, ZHT16MSWIN950 , ZHT16HKSCS31。
详细讨论,请参阅 Note 264294.1 Choosing from WE8ISO8859P1, WE8ISO8859P15 or WE8MSWIN1252 as db character set.
如果想知道哪些语言可以存储在大多数常用字符集中,请参阅 Note 62421.1 Which Character Set Supports Which Language
如果想知道特定字符集中包含哪些字符,请参阅 Note 282336.1 Charts of most current mono-byte Character sets
或者使用 Locale Builder 打开 Oracle 字符集定义,请参阅 Note 223706.1 Using Locale Builder to view the definition of character sets
这里有一个非常优秀的外部资源: http://www.eki.ee/letter/. 在该网站中选择某个语言后,它将显示包含此语言所需的全部字母的所有字符集概览。
请注意,Oracle 不保证该网站中的信息完全正确。
* 对数据库(RDBMS)的升级是不会改变 NLS_CHARACTERSET 的,所以将数据库从 9i 或 10g 升级到 11g 或 12c 后 NLS_CHARACTERSET 还会是原来的值。
* 如果您计划将数据库从一个不推荐的8位字符集(比如US7ASCII 或 WE8ISO8859P1),改为一个推荐的8位字符集(比如WE8MSWIN1252),请参见 C3 中提供的步骤。在没有对源数据库运行 csscan 前,不要尝试做 export 和 import!
从版本 11g 开始,DBCA 默认提供“推荐”字符集列表用作 NLS_CHARACTERSET,出于上述相同的原因,列表中不包含类似于 WE8ISO8859P1 的字符集。请注意,Oracle仍然对这些字符集提供支持,并且根据需要,也可以使用“非推荐”字符集。有关更多信息,请参阅 Note 306411.1 Character Set Consolidation for Oracle Database 11g以及如下文档的”Locale Data” , “Character Sets”部分
11.2. : http://docs.oracle.com/cd/E11882_01/server.112/e10729/applocaledata.htm#NLSPG585
12.1: http://docs.oracle.com/database/121/NLSPG/applocaledata.htm#NLSPG584
如果在 11g 中必需使用 DBCA 中的一个“非推荐”字符集(如 US7ASCII 或 WE8ISO8859P1)创建数据库,则在 11g DBCA 的步骤 9(共 11 个)”Character Sets”选项卡中,钩掉”show recommended character sets only”,然后选择”Choose from the list of character sets”。
在 12c 的 DBCA 中,选择” create a database”,在第2步中选择”advanced mode”,第10步在”Character Sets”选项卡中,钩掉”show recommended character sets only”,然后选择”Choose from the list of character sets”,之后就可以选择不推荐的字符集(比如 US7ASCII 或 WE8ISO8859P1)作为数据库的字符集(NLS_CHARACTERSET)。
关于 ORA-xxxx 错误的语言问题,请参照文档 Note 985974.1 Changing the Language of RDBMS (Error) Messages
C) 在8i, 9i, 10g 和 11g 中更改数据库字符集。
请注意,如果一开始就更改数据库字符集,很有可能*无法*解决显示问题。
因此,请先检查是否可以使用 SQLdeveloper 存储/检索数据,这款工具是无需进行 NLS 配置的“好客户端”。
note 1628060.1 How to diagnose losing characters , getting “funny” output when inserting or selecting other than A-Z,a-z data ( = non English data like Chinese, Russian, Hebrew , insert any language here to the list that is not English) CHAR, VARCHAR2, LONG or CLOB
要确保数据库中没有使用字符集相关的数据类型(CHAR, VARCHAR2, LONG, CLOB)来存储二进制的文件(pdf , doc, docx, jpeg, png等文件)或者加密的数据(passwords).
如果二进制文件(如PDF , doc, docx, jpeg, png等)或者加密的数据(passwords)存成了CHAR, VARCHAR2, LONG 或 CLOB ,那么就很可能会发生数据的丢失,尤其当使用AL32UTF8的数据库的时候(就算没有使用exp/imp)
或者像ORA-29275 或 ORA-600 [kole_t2u], [34]这样的错误就会发生.
唯一支持存储二进制数据或加密的数据的数据类型是LONG RAW 或者 BLOB.
如果你想把二进制数据或加密的数据存储在CHAR, VARCHAR2, LONG or CLOB数据类型里,那么它们在application端必须被转换成”characterset safe”的形式,比如base64.
Note 1297507.1 Problems with (Importing) Encrypted Data After Character Set Change Using Other NLS_CHARACTERSET Database or Upgrading the (client) Oracle Version
C1) 运行 Oracle Application (EBS) 或 PeopleSoft 系统的 数据库字符集转换
请参见文档: Note 124721.1 Migrating an Applications Installation to a New Character Set.
这是唯一的 Oracle applications 提供支持的方法。如果您有任何疑问请创建一个 Oracle Applications 的 SR 以寻求协助。
对于一个Oracle PeopleSoft的数据库,请参照文档note 703689.1 Converting PeopleSoft Systems to Unicode Databases
如果您有任何疑问请创建一个 Oracle PeopleSoft 的 SR 以寻求协助。
C2) 在8i, 9i, 10g 和 11g 中使用“export/import”操作(在 10g 及更高版本中使用Datapump操作)。
您只需导出当前的数据库,然后使用新字符集新建一个数据库,并将数据导入到该数据库中。Export/import (原来的 exp/imp tools 或者 expdp/impdp) 适用于原字符集中的字符在新字符集中都有定义(但它们可能有不同的编码)。
需要注意的是您要存储的字符仍需在原字符集中有正确的定义。
很多时候这个条件都是无法满足的,所以需要通过对源数据库使用 csscan检测这些错误,因此在使用 exp/imp 时,我们建议始终先用 Csscan 检测是否存在问题。
数据丢失(字符在 export/import 之后变成 ? 或者 ¿ )在 export/import 的过程中是不会报错的。
请务必参阅 C3) 或尽早使用 csscan 来避免问题的发生。
如果 csscan 报告有可能发生数据丢失,那么不要使用 export/import
如果要在现有数据库之间导出/导入特定的用户或表,且其中一个数据库是 UTF8 或 AL32UTF8 数据库,则请参阅:Note 1297961.1 ORA-01401 / ORA-12899 While Importing Data In An AL32UTF8 / UTF8 (Unicode) Or Other Multibyte NLS_CHARACTERSET Database.
“旧”的导出/导入功能可以正常工作。10.2.0.4 和 11.1.0.7 补丁集中已修正此问题。
以下链接中包括了此故障的所有现有补丁集:https://updates.oracle.com/download/5874989.html
对于 Windows,修正程序包括在
10.1.0.5.0 Patch 20 (10.1.0.5.20P) 或更高版本中 ( Note 276548.1 )
10.2.0.3.0 Patch 11 (10.2.0.3.11P) 或更高版本中 ( Note 342443.1 )
从技术角度看,只需要在 impdp 端应用补丁集,但是如果您在不同的字符集之间使用 expdp/impdp,我们建议您对所有系统应用补丁集。
注意对于 Transportable tablespaces 的局限: note 297396.1 The Character Set Check Performed When Plugging In a Transportable Tablespace 或者文档 http://docs.oracle.com/cd/E11882_01/server.112/e25494/tspaces.htm#i1007233
C3) 组合使用 ALTER DATABASE CHARACTER SET(8i、9i)/ CSALTER(10g 和 11g)与 “export/import” 操作
在大多数情况下 Csscan 会指出有些数据需要转换为新的字符集(“Convertible”数据),而方法 c2 又会占用太多时间。
在这些情况下,通常可以混合使用 export/import 和 ALTER DATABASE CHARACTER SET(8i、9i)/ CSALTER(10g 和 11g):
a) 导出 Csscan 列出的表中的“Convertible”数据(即代码在当前字符集和新字符集之间会发生转换的字符)
b) truncate 或 drop 掉这些表。
c) 再次运行 csscan,以确保所有数据现已准备好直接移到新字符集中,如果确实已准备就绪,则使用 ALTER DATABASE CHARACTERSET(8i、9i)/CSALTER(10g 和 11g)命令更改数据库的字符集。
d)由于字符集现已更改,我们只需导入在步骤 (a) 导出的数据。导入操作将转换该数据,并使用该新字符集的正确字符代码进行存储。
在 8i、9i、10g 和 11g 中的 8 位字符集之间执行字符集转换的分步指南 。
下面这些文章会指导您完成一些常用的转换操作,其中介绍了如何将上述“组合方法”(如果需要)付诸实践以及如何进行额外的校验:
从 US7ASCII 更改为 WE8MSWIN1252 或从其他 xxIOS8859Pxx 更改为 xx8MSWIN12xx 字符集
Note 555823.1 Changing from US7ASCII or WE8ISO8859P1 to WE8MSWIN1252 in 8i, 9i, 10g and 11g
Note 1213683.1 Changing from US7ASCII or WE8ISO8859P1 or IW8ISO8859P8 to IW8MSWIN1255 in 8i, 9i, 10g and 11g
Note 260022.1 Changing From US7ASCII or WE8ISO8859P1 or AR8ISO8859P6 to AR8MSWIN1256 in 8i, 9i, 10g and 11g
Note 261871.1 Changing EL8ISO8859P7 to EL8MSWIN1253 in 8i, 9i, 10g and 11g
Note 263119.1 Changing EE8ISO8859P2 to EE8MSWIN1250 in 8i, 9i, 10g and 11g
Note 266309.1 Changing WE8ISO8859P9 to WE8ISO8859P1/WE8MSWIN1252 in 8i, 9i, 10g and 11g
Note 246008.1 Changing WE8ISO8859P15 to WE8MSWIN1252 in 8i, 9i, 10g and 11g
其他组合:
Note 1104893.1 Changing US7ASCII TO WE8ISO8859P1 in 8i, 9i, 10g and 11g
Note 1963942.1 Changing WE8DEC to WE8ISO8859P1, WE8ISO8859P15 or WE8MSWIN1252 in 8i, 9i, 10g and 11g
Note 257722.1 Changing WE8ISO8859P1 to WE8ISO8859P15 in 8i, 9i, 10g and 11g
Note 261639.1 Changing WE8MSWIN1252 to WE8ISO8859P15 in 8i, 9i, 10g and 11g
Note 273281.1 Changing WE8ISO8859P15 TO WE8ISO8859P1 in 8i, 9i, 10g and 11g
如果要转换成 ZHS16GBK, ZHT16MSWIN950, ZHT16HKSCS, ZHT16HKSCS31,KO16MSWIN949, JA16SJIS 这样的字符集,步骤同文档 Note:260192.1 Changing the NLS_CHARACTERSET to AL32UTF8 / UTF8 (Unicode) 是一样的。
我们强烈推荐使用 AL32UTF8 做数据库的 NLS_CHARACTERSET。使用上边的字符集没有什么额外的价值。
基本上 AL32UTF8 是大势所趋,AL32UTF8 支持所有其它字符集定义的字符。
C4) 在 8i、9i、10g 和 11g 中将字符集转换为 Unicode (UTF8/AL32UTF8) 的分步指南(包括导出/导入操作)
However N-types are rather poorly supported in (other vendor) programming languages and on application level in general.
但是一般的N-类型在编程语言以及应用的角度上的支持是很差的.为了使用N-类型,应用程序需要显式的支持.
所以Oracle一般建议使用NLS_CHARACTERSET, CHAR, VARCHAR2 , LONG 和 CLOB 这样的数据类型,而不是N-类型的数据类型.
转换到 Unicode ( AL32UTF8 or UTF8 NLS_CHARACTERSET) 可以:
根据文档 Note 260192.1 Changing the NLS_CHARACTERSET to AL32UTF8 / UTF8 (Unicode), 里边也包括了如何使用 csscan 的步骤。
- 或者使用部分 export/import 加 csscan / csalter 将现有的数据库转换掉。
- 或者使用全库 export/import 迁移到一个新的 AL32UTF8 数据库。
或者使用 DMU 工具将现有数据库转换成 AL32UTF8 ,参见 Note 1272374.1 The Database Migration Assistant for Unicode (DMU) Tool
DMU 支持11.2.0.3 及之后版本的数据库以及某些选定的旧版本/平台的组合。
建议在使用 DMU 转换前阅读文档 Note 1272374.1 以及 note 1522722.1 Known Issues With The Database Migration Assistant for Unicode (DMU) Tool version 1.2 (current version)
究竟使用 csscan 加 csalter及部分 export/import,还是使用 DMU 工具,或者使用全库 export/import 我们没有特别的推荐。
一般来说 DMU 工具
- 对用户更友好
- 在转换一个已存在的数据库时,转换过程不需要 export/import
- 如果有很多数据需要修正那么它更简单(通常发生在 US7ASCII 或 WE8ISO8895P1 的数据库上)
- 如果需要操作的数据量比较少那么它比csscan/csalter/部分 export/import 快。
一般来说 csscan 加 csalter 以及部分 export/import ( = 按Note 260192.1的所有步骤操作)
- 喜欢用脚本的人更倾向于使用
- 过去就知道或者使用过
- 如果操作的数据量比较打那么它比 DMU 工具快。
一般来说如果迁移到新的机器那么通常先使用csscan转换,之后使用全库 export/import。 (检查文档 Note 260192.1 的前六步和第12步)
- 导入一个新的AL32UTF8数据库 (如果是迁移到新的机器上)
- 导入到同一台机器的另一个新建的AL32UTF8数据库中 (这样的步骤最少,如果可以容忍停机时间的话)
这三种方式最终的成果是一样的,都是转换成 AL32UTF8。
我们也无法知道究竟哪种方法更快,只能通过测试才能知道。
最好先阅读 Note 788156.1 AL32UTF8 / UTF8 (Unicode) Database Character Set Implications,特别是 “c) the Client side”, 关于 NLS_LANG 通常有很多误解。
将 NLS_CHARACTERSET 从 UTF8 改为 AL32UTF8 (或者从 AL32UTF8 到 UTF8) 可以通过 Note 260192.1 Changing the NLS_CHARACTERSET to AL32UTF8 / UTF8 (Unicode) in 8i, 9i, 10g and 11g. 来实现。
C5) Physical / Logical Standby 数据库如何操作?
如果配置中涉及到 Logical Standby 数据库,那么在修改了主库字符集后 Logcial Standby 数据库必须重建。其它修改 logical standby 数据库的字符集的方式我们都不支持。
Logical standby 数据库需要同主库有相同的 NLS_CHARACTERSET,而且如果说先修改 Logical Standby 的字符集,之后的 SQL apply 也不会成功。
对于版本低于11.1.0.7的 Physical Standy 数据库,备库也需要重建。
对于11.1.0.7 之后的 Physical Standbys 不需要重建, 详见 Note 1124165.1 Changing Primary Database Character Set without Recreating Data Guard Physical Standbys
C6) 如何将数据库从 AL32UTF8/UTF8 改回另外的字符集?
如果您已经有了一个 AL32UTF8 或者 UTF8 但是后来发现应用程序不支持 AL32UTF8 或者 UTF8,那么您可以通过 note 1283764.1 Changing the NLS_CHARACTERSET From AL32UTF8 / UTF8 (Unicode) to another NLS_CHARACTERSET in 8i, 9i, 10g and 11g 将 NLS_CHARACTERSET 改为另外一个。
注意在很多情况下这会造成数据丢失。
D) 在 Oracle 12c 中将数据库字符集修改为 Unicode(UTF8/AL32UTF8)
对于将已经存在的数据库字符集迁移至AL32UTF8 (以及已经废弃的 UTF8),在 12c 中我们提供了工具 Database Migration Assistant for Unicode (DMU)。
DMU 工具是唯一的下一代的用来将字符集迁移至 Unicode 的工具。
DMU 提供的交互界面能极大的简化迁移的步骤并且不需要 DBA 有太多的字符集移植经验,同时它还自动完成了很多移植过程需要的操作。
详见文档 Note 1272374.1 The Database Migration Assistant for Unicode (DMU) Tool.
从 Oracle database 12c开始,迁移 NLS_CHARACTERSET 只能使用工具DMU:Note 1418321.1 CSSCAN and CSALTER To Be Desupported after DB 11.2.
E) 12c Multitenant Container Databases (CDB) 和 Pluggable Databases (PDB) 中字符集的限制:
如何把一个字符集不同的pdb插入到CDB中,请参照请参照
note 1968706.1 ORA-65116/65119: incompatible database/national character set ( Character set mismatch: PDB character set CDB character set )
或者
参见如下文档 Oracle® Database Globalization Support Guide 12c Release 1 (12.1) , 2 Choosing a Character Set , Choosing a Database Character Set for a Multitenant Container Database
http://docs.oracle.com/cd/E16655_01/server.121/e17750/ch2charset.htm#NLSPG1035
DMU工具是唯一一个可以用来把pdb从非Unicode转换成Unicode的工具,参照文档note 1272374.1 The Database Migration Assistant for Unicode (DMU) Tool / 13) How to convert non-Unicode PDB’s to Unicode PDB’s?
F) 其他阅读材料
更改 Oracle Application 数据库的字符集时,还有一些其他注意事项,有关这些事项的完整概述,请参阅以下文章:Note 124721.1 Migrating an Applications Installation to a New Character Set
客户端配置:
Note 788156.1 AL32UTF8 / UTF8 (Unicode) Database Character Set Implications / point “c) the Client side”,
Note 158577.1 NLS_LANG Explained (How does Client-Server Character Conversion Work?)
Note 179133.1 The correct NLS_LANG in a Windows Environment
Note 264157.1 The correct NLS_LANG on Unix Environments
Note 229786.1 NLS_LANG and webservers explained.
有关调试指南的详细信息,请参阅 Note 788931.1 Troubleshooting RDBMS (client and server) NLS Problems (Charactersets, sorts, dates, ..)
Note that NLS_LANGUAGE and NLS_TERRITORY have nothing to do with the ability to *store* characters in a database.
A database using WE8MSWIN1252 NLS_CHARACTERSET and JAPANESE JAPAN as NLS_LANGUAGE and NLS_TERRITORY will *not* allow you to store Japanese as WE8MSWIN1252 doesn’t define Japanese characters.
A database using AL32UTF8 NLS_CHARACTERSET and AMERICAN AMERICA as NLS_LANGUAGE and NLS_TERRITORY *will* allow you to store Japanese (or any other language in the world for that matter).