【问题标题】:Hardcoded strings are cut in half with node-oracle使用 node-oracle 将硬编码的字符串切成两半
【发布时间】:2013-12-02 17:45:32
【问题描述】:

我使用 node-oracle 连接到 Oracle 数据库。

当我从带有西里尔数据的表中选择值时,一切都很好,但如果我这样调用程序:

CREATE OR REPLACE PROCEDURE TEST_ENCODING (CUR OUT SYS_REFCURSOR) AS 
BEGIN
  open cur for
    select 'тест' as hello from dual; -- cyrillic hardcoded text
END TEST_ENCODING;

然后从节点调用它:

connection.execute("call TEST_ENCODING(:1)", [new oracle.OutParam(oracle.OCCICURSOR)],
  function (err, result) {
    console.log(result)
  }
);

结果是:[ { HELLO: 'те' } ](字符串被切成两半)。

数据库配置如下:

NLS_LANGUAGE    AMERICAN
NLS_TERRITORY   AMERICA
NLS_CURRENCY    $
NLS_ISO_CURRENCY    AMERICA
NLS_NUMERIC_CHARACTERS  .,
NLS_CHARACTERSET    CL8MSWIN1251
NLS_CALENDAR    GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE   AMERICAN
NLS_SORT    BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT    DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT  HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY   $
NLS_COMP    BINARY
NLS_LENGTH_SEMANTICS    BYTE
NLS_NCHAR_CONV_EXCP FALSE
NLS_NCHAR_CHARACTERSET  AL16UTF16
NLS_RDBMS_VERSION   11.2.0.3.0

在我的本地环境中:NLS_LANG=AMERICAN_AMERICA.UTF8 (也尝试了NLS_LANG=RUSSIAN_RUSSIA.UTF8RUSSIAN_RUSSIA.AL32UTF8,结果相同)

我的配置:
Mac OS X 10.9
Oracle 客户端 11.2
节点 0.10.22
节点预言机 0.3.4

【问题讨论】:

  • 这个问题有很多可能的来源:不正确的字体选择、错误的 NLS_LANGUAGE 设置或 jdbc 驱动程序的问题。请查看this answer 和相关问题,让我们知道是否有任何解决方案适合您。

标签: oracle node.js node-oracle


【解决方案1】:
  1. 似乎目前在node-oracle 中不支持除UTF8 之外的编码,因为node.js 不支持本机编码(proof)。

  2. 要正确处理字符串,您需要将客户端上的 NLS_LANG 参数设置为与数据库中相同的值 (CL8MSWIN1251)

因此,您可以从 2 种变体中进行选择:

A) Migrate databaseUTF8 编码。

B) 修补 node-oracle source 以将字符串和 CLOB 转换为 UTF8,然后将其内容返回给 node.js,并在将其传递给 Oracle 之前应用从 UTF8CL8MSWIN1251 的转换。 OCI interface 有一个 functions 用于此类转换。例如。对于您的本地目的,在utils.h 中修补OBJ_GET_STRING 宏就足够了

附: node-oracle 目前看起来非常简单,所以要为许多惊喜做好准备(例如不支持 BLOB 和集合、缺少连接设置等等)。

【讨论】:

  • 是的,问题似乎出在 node-oracle 字符串转换的某个地方,尽管看起来特定的宏用于从 js 中放置 oracle 字符串,而不是相反.. .
【解决方案2】:

这可能是因为您的数据库主字符集是 CL8MSWIN1251,而本地设置指定了 UTF8。

NLS_CHARACTERSET    CL8MSWIN1251

变量 NLS_LANG 指定如何解释本地环境

NLS_LANG = language_territory.charset

NLS_LANG 的最后一部分提供有关本地字符集的信息,它用于让 Oracle 知道您在客户端使用的字符集,以便 Oracle 可以进行正确的转换。当双重表中的值的字符集未正确识别时,表中的值可能已正确转换。

请尝试将 NLS_LANG 变量设置为 AMERICAN_AMERICA.CL8MSWIN1251(或 RUSSIAN_RUSSIA.CL8MSWIN1251,没关系)

【讨论】:

  • 不,现在我得到 [{HELLO: '����'}],它的长度正确,但内容不正确。此外,来自具有西里尔数据的表的每个查询现在都返回 �s
  • 能否请您稍微更改一下原始程序并添加 convert ('тест','UTF8') 而不是仅 'тест' 并使用 UTF8 本地字符集运行它?
  • 结果是 { HELLO: 'С‚Р' } (为调试目的添加了字符串的缓冲区表示)。
  • AMERICAN_AMERICA.CL8MSWIN1251 必须在客户端设置并且字符数可以。如果你只是将常量字符串'тест' 输出到控制台会发生什么?是否正确显示?我的意思是console.log('тест') ...
  • @F0RR,嗨。我在 node-oracle 中对 AMERICAN_AMERICA.CL8MSWIN1251 有同样的问题。你有什么解决办法吗?提前致谢。
【解决方案3】:

您确定您的源代码具有 UTF-8 字符集吗?
如果问题仅与硬编码符号有关,则您用于 Oracle 开发的 GUI 可能不支持 UTF-8
我的包中的特殊字符(如 ¥)和将特殊字符转换为一些不可读的 sql*plus 有类似的问题

【讨论】:

    猜你喜欢
    • 2015-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    相关资源
    最近更新 更多