在 Unix 环境中正确设置 NLS_LANG (文档 ID 1548858.1)

在 Unix 环境中正确设置 NLS_LANG (文档 ID 1548858.1)


文档内容

目标

 

解决方案

 

 

1- 检查 locale 的设置,如果需要,请更正。

 

 

2- 检查所选择的 locale 是否确实已安装,如果需要,请安装。

 

 

3- 检查 telnet/ssh 软件是否已正确配置。

 

 

4- 设置 NLS_LANG 并测试。

 

 

5- 如果上述方法都不起作用怎么办?

 

 

6- 进行更深入的调试。

 

 

7- Locale 和 NLS_LANG 是否*需要*与数据库字符集匹配?

 

参考


适用于:

Oracle Database - Enterprise Edition - 版本 8.0.3.0 和更高版本
Oracle Database - Standard Edition - 版本 8.0.3.0 和更高版本
本文档所含信息适用于所有平台

目标

 说明如何在 Unix 环境中正确设置 NLS_LANG。

解决方案

  

要调试显示问题(当您看到奇怪的符号或字符,如 "?" , "¿" or "ÃÂ"),请首先使用 Oracle SQL Developer 进行调试。
Oracle SQL Developer 是一款无需在客户端进行 Oracle NLS 配置的“已知的可用客户端”。请使用此链接下载最新版本 http://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/ 。Oracle SQL Developer 无需安装 Oracle 客户端。
一旦安装(最好安装在 Microsoft Windows 客户端上),请执行以下操作:

  •  使用通过 Oracle SQL Developer 在测试表中插入的新数据进行测试
  •  在 Oracle SQL Developer 中查询现有(应用程序)数据

如果通过 Oracle SQL Developer 在测试表中插入的新数据在 Oracle SQL Developer 中正确显示,则您可以确定 NLS_CHARACTERSET 支持这些字符,因此数据库端配置(也就是 datatype 和 NLS_CHARACTERSET)正常,问题在于客户端。新数据如果在 Oracle SQL Developer 中正确显示,则可以用作检查客户端配置的“参考”。
如果现有应用程序数据在 Oracle SQL Developer 中 正确显示,则在尝试配置任何其他数据之前,应首先检查当初执行插入(inserting)的客户端配置,因为此数据在数据库中未正确存储。
如果现有应用程序数据在 Oracle SQL Developer 中能 正确 显示,则您可以确定此数据在数据库中已正确存储,问题只存在于执行查询(selecting)的客户端。

如果您看到字符显示为方块,则可能需要更改 Oracle SQL Developer 中的字体,所有 Microsoft Windows 系统中通常都安装了“Arial Unicode MS”,这种字体可支持各式各样的字符。
在 Oracle SQL Developer 中更改字体的方法:“Tools(工具)”,“Preferences(首选项)”,展开“Code Editor(代码编辑器)”并选择“Font(字体)”。在下拉框中选择您想要的字体。
请注意,就这点而论,因字体原因丢失的字符(比如您看见方块)与“丢失的字符”(您看见 "?" , "¿" or "ÃÂ" ,而非方块)毫无关系,因为这些字符存在于工具中,且在客户端可用,但只是客户端操作系统不知道如何显示它们。

1- 检查 locale 的设置,如果需要,请更正。

此处所用示例是配置 Unix 环境以便能够在 Unix 计算机的 shell 中使用 Unicode (UTF-8)、配置 Telnet/SSH 软件、以及将 NLS_LANG 设置为 UTF8 / AL32UTF8 以用于 sqlplus。有关在数据库级别使用 Unicode 的更多信息,请参阅 Note:788156.1 AL32UTF8 / UTF8 (Unicode) Database Character Set Implications


要查看当前设置,请使用 “locale” 命令,如下所示:

$ locale

输出示例:

LANG=fr_FR
LC_CTYPE="fr_FR.iso885915@euro"
LC_COLLATE="fr_FR.iso885915@euro"
LC_MONETARY="fr_FR.iso885915@euro"
LC_NUMERIC="fr_FR.iso885915@euro"
LC_TIME="fr_FR.iso885915@euro"
LC_MESSAGES="fr_FR.iso885915@euro"
LC_ALL=fr_FR.iso885915@euro


大多数 Unix 版本默认设置为:

$ locale

LANG=
LC_CTYPE="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_MESSAGES="C"
LC_ALL=


“C”是指 US7ASCII,这意味着仅可显示 a-z、A-Z 和 0-9。

我们建议尽可能使用 UTF-8,如下所示:

$ locale

LANG=en_US
LC_CTYPE="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_ALL=en_US.UTF-8


如果您已经选择了一个值,例如在 Linux 上使用 “en_US.UTF-8”,可进行如下设置:

$ export LC_ALL=en_US.UTF-8



% setenv LC_ALL en_US.UTF-8


请注意,此命令的输出/语法在不同 Unix 环境中并不完全相同。如果您对如何在特定 Unix/Linux 版本中配置用户环境有任何问题,请咨询您的 OS 供应商。

2- 检查所选择的 locale 是否确实已安装,如果需要,请安装。

要查看所有安装的 locale,请执行以下语句:

$ locale -a

示例输出:

$ locale -a

POSIX
common
en_US.UTF-8
C
iso_8859_1
iso_8859_15
en_CA
en_CA.ISO8859-1
en_US
en_US.ISO8859-1
en_US.ISO8859-15
en_US.ISO8859-15@euro
fr_CA
fr_CA.ISO8859-1
th
th_TH
th_TH.TIS620
ja
...


这将列出 Unix 计算机上所有已安装的 locale。
例如,如果您想要使用 “fr_FR.iso885915@euro”,但它不在列表中,则您需要先安装它。
如果您将用户环境设置为未安装的 locale,您不会收到错误消息,但该设置可能不起作用。
请注意,您需要安装完全匹配的 locale,如果您安装了 “fr_FR.UTF-8”或“UTF-8”,但想要使用 “en_US.UTF-8”,则需要安装 “en_US.UTF-8”。

Locale 参数语法为 “language(_territory)(.encoding)(@modifier)”。language(_territory) 部分用于确定日期的默认格式、OS 级别的接口语言等(有关更多信息,请参阅系统文档),因此,这部分的设置需要您来决定,而不是 Oracle;但是,如果您希望使用 Unicode shell 环境,则最后的 (.encoding) 部分需要为 UTF-8。注意 Unix Locale 的 Language 和 Territory 设置与在 shell 中使用字符 的能力无关。Locale 设置为 ja_JA.ISO8859-1不代表您可以使用日文,因为 ISO8859-1 不识别日文字符。但 Locale 设置为 en_US.UTF-8 将允许在 shell 中使用日文(假定您的 telnet/ssh 客户端设置正确)。


在上边的示例中,“en_US.UTF-8” 存在于列表中,因此我们可以在此服务器上使用该设置。

3- 检查 telnet/ssh 软件是否已正确配置。

您需要检查 telnet/ssh 软件是否已正确配置。telnet/ssh 软件负责将 Unix locale 转换给客户端环境(多半为 Windows 系统)。

我们建议首先使用免费的 PUTTY 客户端进行尝试,据我们所知,它是与 Unicode 最佳兼容的一款客户端工具。您可从此站点下载 Putty:http://www.chiark.greenend.org.uk/~sgtatham/putty/

如示例中一样,在 Unix 端使用 “en_US.UTF-8”,则在 Putty 中更改如下设置:

打开配置窗口,导航到“Window(窗口)”、“Translation(转换)”,并将“Received data assumed to be in which character set(假定接收到的数据使用此字符集)”设置为“UTF-8”。这需要与 Unix shell 端的编码匹配。

导航到“Window(窗口)”、“Appearance(外观)”,然后在“Font used in the terminal window(终端窗口中使用的字体)”中选择一种字体,以便支持您想要使用/查看的语言。

请注意,编码/字符集与字体之间的根本区别在于,编码/字符集定义了每种编码包括哪些字符,而字体用于 OS 在屏幕上“绘制”由编码定义的字符。使用 Telnet/ssh 等基于文本的仿真程序,远程端不会向客户端发送/从客户端接收“字符”,而使用特定字符集进行编码,客户端 OS 使用 Telnet/ssh 客户端的字体在屏幕上绘制这些字符。这意味着在使用任何字体之前,客户端和远程端首先需要就使用的编码达成一致。

在 Windows 客户端,大多数非亚洲语言可以使用默认的“Courier New” Windows 字体,“Arial Unicode MS”为更加完整的字体。“Arial Unicode MS”通常在所有安装了 Office 2002 或更高版本的 Windows 客户端均可用,可支持各式各样的字符。要了解此字体支持哪些语言,请参阅 http://support.microsoft.com/kb/q287247/ 。如果未安装 office 2002,则可以尝试 GNU FreeFont http://www.gnu.org/software/freefont/index.html 集合。另一个关于 Unicode 字体的非常优秀的资源是 Alan Wood's website。例如,Shareware“Code2000”字体是最完整的“通用”字体之一。

在 Windows 上,Windows 工具“字符映射表”可用于查看字体中包含哪些字符,或者您可以在编辑器中(如 Wordpad)输入字符并选择字体,然后看这些字符是否正确显示。

请务必检查 telnet/ssh 客户端配置,几乎在所有情况下,在“Unix 提示符”中显示字符存在问题的原因都是由于 telnet/ssh 客户端配置不正确导致,或者是正在使用不可配置的 telnet/ssh 客户端而导致,如标准 Windows telnet。

如果使用 Putty 可以正确显示,但使用您的 telnet/ssh 软件包却不可正确显示,请咨询您的 telnet/ssh 软件供应商。

如果您不使用 telnet/ssh 客户端而使用“真正的”Unix 显示器,请参阅 Note 265090.1 How to check Unix terminal Environments for the capability to display extended characters.

4- 设置 NLS_LANG 并测试。

当您执行完下列操作后:
1)
正确配置 LC_ALL  
2) 确认所使用的 locale 已安装
3) 配置好 telnet/ssh 客户端
然后您就可以使用 NLS_LANG 匹配 locale。

NLS_LANG 的构成为:NLS_LANG=_.

以 locale “en_US.UTF-8”为例,这意味着应该将 NLS_LANG 设置为 =AMERICAN_AMERICA.AL32UTF8;如果 locale 设置为“fr_FR.UTF-8”,则相应的 NLS_LANG 设置将为 FRENCH_FRANCE.AL32UTF8。

请注意:
* UTF-8 (Unix)
和 UTF8/AL32UTF8 (Oracle) 的表示法之间的区别
* NLS_LANG 的 NLS_LANGUAGE 和 NLS_TERRITORY 设置 与在客户端上“查看”字符/在数据库中存储字符的能力无关。 NLS_LANG 设置为 JAPANESE_JAPAN.WE8ISO8859P15 将不允许存储日文,因为 WE8ISO8859P15 不识别日文字符。但 NLS_LANG 设置为 AMERICAN_AMERICA.UTF8 将允许使用/存储日文(假定您的 telnet/ssh 客户端和 Locale 设置正确,且您的数据库可以存储日文 - 例如使用 UTF8 或 AL32UTF8 NLS_CHARACTERSET 的数据库)
* 要使 NLS_LANGUAGE 和 NLS_TERRITORY 匹配 LC_ALL 中的 language(_territory) 值,请在 database globalizaton support guide appendix A. 中查看相应的 Oracle 语言和地区值。


因此,以 Unix 用户身份登录并执行以下操作:

a) 对照 locale 检查 LC_ALL 是否设置正确(假定此处为 en_US.UTF-8)

b) 仔细检查 Telnet/ssh 客户端配置(假定此处 Putty 按第 3 点所述进行配置)

c) 设置 NLS_LANG 以匹配 locale 设置

$ export NLS_LANG=AMERICAN_AMERICA.AL32UTF8



% setenv NLS_LANG AMERICAN_AMERICA.AL32UTF8

之后通过下边的小窍门检查 sqlplus 侦测到的 NLS_LANG 设置:

$ sqlplus /nolog
SQL>@.[$NLS_LANG].

如果您得到下边的结果:

SQL>@.[$NLS_LANG].
SP2-0310: unable to open file ".[AMERICAN_AMERICA.AL32UTF8]..sql"

'[]'中包含的"文件名"就是 sqlplus 将会使用的 NLS_LANG 设置。

如果您得到下边的结果:

SQL>@.[$NLS_LANG].
SP2-0310: unable to open file ".[$NLS_LANG]..sql"

那么表示 NLS_LANG 没有设或者 sqlplus 没有侦测到。

如果您得到" SP2-0310: unable to open file ".[$NLS_LANG]..sql" " 但是下边的命令能返回 AMERICAN_AMERICA.AL32UTF8

SQL>HOST ECHO $NLS_LANG

那么表明 NLS_LANG 设置了但是没有在环境中 *export*


d)
使用 sqlplus 连接到数据库并查询一些数据。

一个很好的检查方法是执行以下语句“select UNISTR('\20AC') from dual;”。如果您选择使用9i 或更高版本数据库,和一个正确的 UTF-8 或 ISO8859-15 Unix 环境,则一个欧元符号会被正确的显示出来,因为这样的环境可以正确处理欧洲语言(AL32UTF8、WE8MSWIN1252、...)。如果可以显示欧元符号但数据库中存储的数据未正确显示,则表明客户端已正确配置,但数据库中的现有数据现在/过去未正确存储。您将需要更正数据库中的现有数据,直至其可在正确配置的客户端显示 Note:225938.1 Database Character Set Healthcheck.


如果此方法有效,则将用户配置文件中的 NLS_LANG 也设置为这个值以用于 sqlplus。

如果已完成,则您已针对在 sqlplus 中交互式插入和查询数据进行了正确配置。

但是,这并不意味着此设置可用于所有应用程序。
NLS_LANG 用于让 Oracle 客户端知道哪些编码/字符集数据将传输到客户端库。如果您在此 Unix 计算机上运行 Web 应用程序且输出 iso-8859-1 数据,则对于应用程序,正确的 NLS_LANG 为 WE8ISO8859P1(即使 Unix locale 为 UTF-8)

Note 229786.1 NLS_LANG and webservers explained.
Note 115001.1 NLS_LANG Client Settings and JDBC Drivers

5- 如果上述方法都不起作用怎么办?

如果您未看见预期的字符,则请再次检查您的设置。剩余的最常见问题是您的 Telnet/ssh 仿真程序未正确配置。
然而,也可能是您的数据库中数据不正确。

一个简单的检查方法是:

使用 Windows 客户端,从以下地址下载并安装 SqlDeveloper http://www.oracle.com/technology/products/database/sql_developer/index.html ,连接到您的数据库并查看数据在该工具中是否正确显示。
如果数据可以在 SqlDeveloper 中显示,则数据库中的数据是正确的,问题在于客户端。
如果数据未在 SqlDeveloper 中显示,则表明数据库中的数据不正确,这意味着即使您的客户端已正确配置,数据也无法正确显示。

较难的检查方法是:

如果您使用 select 语句,例如“select ename from scott.emp where empno='7369';”来返回一行数据,则执行以下语句“select dump(ename,1016),ename from scott.emp where empno='7369';”。
您可以在以下文档中查看代码是否匹配您期望数据库字符集中的字符 ( select value from NLS_DATABASE_PARAMETERS where parameter='NLS_CHARACTERSET'; ) Note 282336.1 Charts of most current mono-byte Character sets,或者如果您使用的是 (AL32)UTF8 数据库,请使用 Note 69518.1 Storing and Checking Character Codepoints in a UTF8/AL32UTF8 (Unicode) database

如果您不知道问题是什么原因造成的,请新开一个服务请求,参阅以下文档并提供所需信息:
* Note 226692.1 Finding out your NLS Setup 文档中要求的信息。
* 在您的环境中执行这个select语句“select dump(ename,1016),ename from scott.emp where empno='7369';”并用 spool  保存结果到文件。(!请勿直接复制粘贴!)

6- 进行更深入的调试。

第 1-4 步应足以解决 99% 的问题,本文档的剩余部分将讨论深入调试

在某些平台上,使用下列语法可以有效地获取关于
实际使用的代码页的更多详细信息:

$ locale LC_CTYPE | head

HP-UX 环境中的输出示例:
""
""
"iso885915"
""
Linux 环境中的输出示例:
upper;lower;alpha;digit;xdigit;space;print;graph;blank;cntrl;punct;alnum;combining;combining_level3
toupper;tolower;totitle
16
1
ISO-8859-15
70
84
1
0
1

$ locale LC_CTYPE | head
upper;lower;alpha;digit;xdigit;space;print;graph;blank;cntrl;punct;alnum;combining;combining_level3
toupper;tolower;totitle
16
6
UTF-8
70
84
1
0
1


在 Solaris、AIX、TRU64 上,此语法不能提供相关的补充信息。
要查找关于这些设置的更多详细信息:
在 Solaris 上,请查看 /usr/lib/locale。
在 AIX 上,请查看 /usr/lib/nls/README
在 TRU64 上,请查看 /usr/lib/nls
在 HP-UX 上,请查看 /usr/lib/nls/config
在 Linux 上,请查看 /usr/share/locale/locale.alias


如何检查操作系统管理的字符编码:

要了解 Unix 环境中针对字符所生成的字符编码,
可以按如下所示使用“od”命令(使用 iso-8859-1 locale 的示例):

$ od -xc
é
0000000 00e9
351 \0
0000001

正如您所见,hexa-decimal 编码 e9 对应于“é”(小写 e 重读音节)
351 是对应的八进制值(八进制为 od 命令的固有状态)。

您还可以使用“echo”命令检查对应于字符编码的字符,如下所示:

对于 Solaris、AIX、HP-UX、TRU64:

$echo '\0351'
é

对于 Linux:

$echo -e '\0351'
é

正如您所见,echo 使用八进制值,因此您需要将要检查的值转换为八进制。

7- Locale NLS_LANG 是否*需要*与数据库字符集匹配?

不需要,Locale 和 NLS_LANG 设置(如果适用,还包括 telnet/ssh config)需要互相匹配,但从技术角度看它们均与数据库字符集无关,并且它们仅针对该客户端环境相关。

假定您使用 AL32UTF8 NLS_CHARACTERSET 数据库。如果将 Unix 环境配置为(例如)fr_FR.iso885915@euro(相匹配的 NLS_LANG 为 FRENCH_FRANCE.WE8ISO8859P15),则您可以在 Unix shell 中查看/插入欧元字符和法文或西班牙文,但无法查看/插入俄文或中文(也就是 iso885915 中未定义的任何语言)。
然而,如果您使用可以存储/处理这些语言的远程客户端(例如使用 Sqldeveloper 的 Windows 客户端),则可以向 AL32UTF8 数据库插入这些语言或从该数据库选择这些语言。原因很简单,因为服务器 NLS_LANG/Locale 设置仅在服务器本身作为客户端的情况下有关。

许多客户都遇到过这样的麻烦,由于将数据库 NLS_CHARACTERSET 更改为 (AL32)UTF8 从而需要“更正”Unix shell,其实只要不将 Unix 服务器本身作为客户端用于数据输入,则可以免去这些麻烦。您其实更应该担心的是最终用户实际插入数据的客户端。能够在服务器上使用 sqlplus 查看/插入中文可能是不错的体验,但即使奏效,这也与您的 Windows 客户端(例如)无关,因为 Windows 客户端设置与 Unix 端完全无关。对于 Windows 客户端,请参阅 Note 179133.1 The correct NLS_LANG in a Windows Environment

请注意,在服务器上加载普通文本文件时,sqlldr 的字符集取决于该文本/普通文件的字符集,而不是数据库字符集或所使用的 Unix locale,请参阅 Note 227330.1 Character Sets & Conversion - Frequently Asked Questions / point 18. What is the best way to load non-US7ASCII characters using SQL*Loader or External Tables?

你可能感兴趣的:(在 Unix 环境中正确设置 NLS_LANG (文档 ID 1548858.1))