2

我在字符编码方面遇到了严重问题。提供一些背景:

  1. 我有土耳其业务用户,他们在 Unix 屏幕上用土耳其语输入一些数据。
  2. 我的数据库 NLS 参数设置为AMERICANWE8ISO8859P1而 Unix设置NLS_LANGAMERICAN_AMERICA.WE8ISO8859P1.
  3. 土耳其业务能够在 UNIX 屏幕和 TOAD 上看到所有土耳其语字符,而我不能。我只能在西欧字符集中看到它们。

在业务端:ÖZER İNŞAAT TAAHHÜT VE
在我们端:ÖZER ÝNÞAAT TAAHHÜT VE

如果您注意到土耳其字符İŞ正在转换为 ISO 8859-1 字符集。但是,所有设置(db 和 unix 中的 NLS 参数)在两端都相同ISO8859-1- (西欧)

通过一些研究,我可以理解 - 土耳其机器可以通过实时转换来显示土耳其数据(数据库 NLS 设置被本地 NLS 设置覆盖)。

现在,我有一个在我的数据库中运行的接口——有一些 PL/SQL 脚本(通过 shell 脚本运行)从数据库中提取一些数据并将它们假脱机到一个 unix 路径上的 .csv 文件。然后该 .csv 文件通过 MFT(托管文件传输)传输到外部系统。

问题是-Exract 从不包含任何土耳其字符。每个土耳其字符都被转换为西欧字符集,并像这样进入外部系统,这被视为数据转换/丢失的情况,我的业务真的很不开心。

谁能告诉我 - 我怎么能保留所有的土耳其字符?

PS:外部系统的字符集可以设置为 ISP8859-9 字符集。

提前谢谢了。

4

2 回答 2

6

如果您说您的数据库字符集是 ISO-8859-1,即

SELECT parameter, value
  FROM v$nls_parameters
 WHERE parameter = 'NLS_CHARACTERSET'

返回 a valueofWE8ISO8859P1并且您将数据存储在CHARVARCHARVARCHAR2列中,问题是数据库字符集不支持完整的土耳其字符集。如果字符不在ISO-8859-1 代码页布局中,则无法将其正确存储在由数据库字符集控制的数据库列中。如果您想将土耳其语数据存储在 ISO-8859-1 数据库中,您可以使用替代字符(即用 S 代替 Ş)。但是,如果您想支持所有土耳其语字符,则需要迁移到支持所有这些字符的字符集——ISO-8859-9 或 UTF-8 都比较常见。

然而,更改现有数据库的字符集并非易事。无论您使用什么版本的 Oracle,Globalization Support Guide 中都有一章介绍了字符集迁移。如果您想迁移到 Unicode 字符集(这通常是首选方法,而不是坚持使用单字节 ISO 字符集之一),您可以利用Oracle Database Migration Assistant for Unicode

此时,您通常会看到反对意见,即至少某些应用程序“正确”地查看数据,因此数据库必须支持土耳其语字符。问题是,如果您设置NLS_LANG不正确,则可能会完全绕过字符集转换,这意味着客户端上字符的任何二进制表示都会被持久化,而无需修改数据库。只要读取数据的每个进程都以NLS_LANG相同且错误的方式配置它们,事情就可能看起来有效。但是,您会很快发现其他一些应用程序将无法配置它们的NLS_LANG同样不正确。例如,Java 应用程序总是希望在内部将数据库中的数据转换为 Unicode 字符串。因此,如果您将数据错误地存储在数据库中,就像听起来那样,则无法让这些应用程序正确读取它。如果您只是在 shell 脚本中使用 SQL*Plus 来生成文件,那么几乎可以肯定的是,您的客户端配置不正确,因此数据文件看起来是正确的。但是让现有的错误配置持续存在是一个非常糟糕的主意。你敞开心扉将来会出现更大的问题(如果您还没有遇到),当您发现 Oracle 导出实用程序之类的工具损坏了数据导出或当您想使用无法正确配置的工具来查看数据时。尽早纠正问题会更好。

于 2012-09-27T19:03:07.533 回答
1

只需将NLS_LANG参数设置AMERICAN_AMERICA.WE8ISO8859P9为土耳其语就足够了。

于 2018-08-21T17:09:27.843 回答