Oracle设置默认NLS_LANG

时间:2012-03-15 14:25:32

标签: linux oracle utf-8

我在RHEL6上运行Oracle数据库11g。如果没有客户端NLS_LANG设置某些utf8字符的长度为2.在NLS_LANG = AMERICAN_AMERICA.UTF8设置后,长度仅为1。 怎么能打赌整个数据库的默认NLG_LANG改变了?我不想仅为会话更改此值,或者像linux中的环境变量一样。是否有可能为数据库设置一般性?

SQL> select length('á') from dual;

LENGTH('??')
------------
           2

# export NLS_LANG=AMERICAN_AMERICA.UTF8

SQL> select length('á') from dual;

LENGTH('á')
-----------
          1

非常感谢任何想法

2 个答案:

答案 0 :(得分:1)

由于数据库字符集是AL32UTF8,当您将客户端NLS_LANG设置为UTF8时,您告诉Oracle绕过通常在客户端和服务器之间传输数据时发生的字符集转换。这是非常危险的,因为这意味着如果客户端以任何其他编码方式发送数据,则存在无效数据将存储在数据库中的巨大风险。在这种情况下,返回1的LENGTH调用将错误编码的数据发送到数据库。最有可能的是,客户端操作系统使用类似ISO-8859-1字符集的数据表示数据,其中á是单字节字符(二进制值0xE1)。当客户端将数据发送到数据库时,它正在发送0xE1并告诉数据库“信任我,这是有效的UTF-8数据”。数据库不打算检查二进制数据以注意0xE1不是UTF-8字符集中任何字符的有效二进制表示。但是现在如果某个其他客户端出现正确配置并要求进行字符集转换并且数据库在某些列中存储了0xE1,则字符集转换代码将运行,标识0xE1不是有效的UTF-8字符,并返回一个替换字符(通常是'?')而不是á到正确配置的客户端。

由于数据库字符集是UTF-8,您可能希望'á'字符的长度为2. UTF-8是可变宽度字符集。属于US7ASCII字符集的字符用1个字节表示,大多数西欧字符(如'á')用2个字节表示,大多数亚洲字符用3个字节表示。有一些罕见的字符需要4个字节。

您的NLS_LANG需要设置为与客户端系统支持的字符集匹配。您很少有一个具有本机UTF-8支持的客户端系统。由于您的客户端设置将覆盖在数据库级别设置的任何内容,这意味着需要配置每个客户端以设置适当的环境变量。 NLS_LANG FAQ how to determine the correct NLS_LANG setting for a Unix client上有一个部分。

答案 1 :(得分:1)

这可能发生了:

  • 您的客户端字符集必须类似CP1252或ISO-8859-15,而实际上您的客户端确实使用UTF8。
  • 在此字符集(UTF8)中,符号á占用两个字节,因此您的客户端发送这两个字节,同时告诉Oracle将这些字节视为CP1252。在CP1252中,两个字节的两个字节代码导致DB将输入解释为两个字符,因此length('à')等于2(如果插入此字符串,则插入的结果不等于à
  • 当您正确设置字符集时,oracle将输入正确地视为单个字符,其长度为1(仍为两个字节)。

结论:正确设置您的客户端字符集或者您将获得翻译错误(您不会以这种方式获取非法字符,但您可能会得到奇怪的符号(¿)。

数据库字符集在创建时设置,通常通过export / create blank database / import进行更改。