17

我在将 unicode 插入 Oracle 架构时遇到问题,我认为数据库是 Oracle 11g 实例,但目前还不确定。我在 OS X 10.6.8 上使用 python 2.6.1(这是 python 的系统版本)并使用从 sourceforge.net 下载的 cx-Oracle 驱动程序模块版本 5.1,构建并安装到 virtualenv 1.6.1 实例网站包可见。我的脚本如下

  import cx_Oracle

  connection = cx_Oracle.connect(
      "<name>/<password>@<host>/<service-name>"
      )
  cursor = connection.cursor()
  result = cursor.execute(u"create table UNICODE_TEST (id NUMBER(6), text NCLOB not NULL)")

  raw_text = open("test.txt",'r').read()
  if isinstance(raw_text,str):
      raw_text = raw_text.decode("utf_8")

  statement = u"insert into UNICODE_TEST (id, text) values (1,'%s')" % raw_text
  result = cursor.execute(statement)

我创建一个连接,创建游标,执行一个语句来创建一个测试表,其中包含 NUMBER 和 NCLOB 类型的 id 和文本字段。我打开一个文件,其中包含我知道的以 UTF-8 编码的文本,将字符串解码为 un​​icode。在 unicode 字符串中创建一个插入语句并执行该语句,结果就是这个错误。

  Traceback (most recent call last):
    File "unicode-test.py", line 19, in <module>
      result = cursor.execute(statement)
  UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 170: ordinal not in range(128)

在将我的语句插入 Oracle 模式之前,有些东西试图将其编码为 ASCII。所以我开始四处寻找以更好地了解 cx-Oracle 如何处理 unicode,并在我从 sourceforge.net 下载的 cx-Oracle 源代码的 HISTORY.txt 中找到了这一点

从 5.0.4 到 5.1 的更改
1) 删除对 UNICODE 模式的支持,并允许在任何可能传入字符串的地方传递 Unicode。这意味着字符串将使用 Python 中的 NLS_LANG 环境变量的值传递给 Oracle 3.x 也是如此。这样做消除了使用 UNICODE 模式发现的一堆问题,还消除了 Python 2.x 中一个不必要的限制,例如 Unicode 不能用于连接字符串或 SQL 语句。...

我的假设是 NLS_LANG 环境变量设置为“ascii”或其他等效变量,因此我尝试将 NLS_LANG 设置为“AL32UTF8”,我认为这是 unicode 的正确值,并在创建连接之前设置新值。

  os.environ["NLS_LANG"] = "AL32UTF8"
  connection = cx_Oracle.connect(
      "<user>/<password>@<host>/<service-name>"
      )
  cursor = connection.cursor()
  ...

但我得到这个错误。

  Traceback (most recent call last):
    File "unicode-test.py", line 11, in <module>
      "<user>/<password>@<host>/<service-name>"
  cx_Oracle.DatabaseError: ORA-12705: Cannot access NLS data files or invalid environment specified

所以看起来我无法篡改 NLS_LANG 值。

这是我现在的问题。我是否遗漏了一些简单的东西,例如不正确的列类型?是 cx-Oracle 驱动程序的问题吗?在构建 cx-Oracle 模块时,我是否需要设置“WITH_UNICODE”环境变量,我该怎么做?是 Oracle 实例的问题吗?我对 Oracle 的经验很少,也从未与 Oracle 和 python 一起工作过。我花了两天时间来解决这个问题,并希望在我去 DBA 小组之前更好地了解这个问题是什么。

谢谢,

4

1 回答 1

15

设置环境变量是正确的方法,但“AL32UTF8”不是 NLS_LANG 的正确值。要获得在您的 Oracle 实例中使用的 NLS_LANG 的正确值,请执行

SELECT USERENV ('language') FROM DUAL  
于 2013-04-04T05:49:34.820 回答