Невозможно вставить Unicode с помощью cx-Oracle

У меня проблема с вставкой юникода в схему Oracle, я думаю, что база данных является экземпляром Oracle 11g, но на данный момент я не уверен. Я использую python 2.6.1 в OS X 10.6.8 (это системная проверка python), и я использую модуль версии cx-Oracle версии 5.1, загруженный с sourceforge.net, встроенный и установленный в экземпляр virtualenv 1.6.1 с видимыми областями сайта. Мой script выглядит следующим образом

  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)

Я создаю соединение, создаю курсор, выполняю statment для создания тестовой таблицы с идентификатором и текстовым полем типов NUMBER и NCLOB. Я открываю файл, содержащий то, что я знаю, для кодирования текста в UTF-8, декодирует строку в unicode. Создайте вставку в строку 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)

Что-то пытается закодировать мой оператор как ASCII, прежде чем вставлять его в схему Oracle. Поэтому я начал охоту вокруг, пытаясь лучше понять, как cx-Oracle обрабатывает unicode и нашел это в HISTORY.txt источника cx-Oracle, который я загрузил с сайта sourceforge.net.

Изменения от 5.0.4 до 5.1
1) Удалите поддержку режима UNICODE и разрешить использование Unicode в       всюду может передаваться строка. Это означает, что строки будут       передается Oracle, используя значение среды NLS_LANG       переменная в Python 3.x. Это устраняло множество проблем       которые были обнаружены с использованием режима UNICODE, а также удалены ненужные       ограничение в Python 2.x, что Unicode не может использоваться в строках подключения       или SQL, например.       ...

Мое предположение заключается в том, что для переменной среды NLS_LANG установлено значение "ascii" или какой-то эквивалент, поэтому я пытаюсь установить NLS_LANG на "AL32UTF8", который, как я считаю, является правильным значением для юникода, и установите новое значение перед созданием моего соединения.

  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? Нужно ли устанавливать переменную среды WITH_UNICODE при построении модуля cx-Oracle и как мне это сделать? Является ли проблема с экземпляром Oracle? У меня мало опыта работы с Oracle и никогда не работал с Oracle и python. Я потратил два дня на работу над этой проблемой и хотел бы лучше понять, в чем проблема, прежде чем я перейду в группу DBA.

Спасибо,

Ответы

Ответ 1

Настройка переменной среды - это правильный путь, но "AL32UTF8" не является правильным значением для NLS_LANG. Чтобы получить правильное значение NLS_LANG, используемого в вашем экземпляре Oracle, выполните

SELECT USERENV ('language') FROM DUAL