2013-01-09 11 views
15

ユニコードをOracleスキーマに挿入する際に問題が発生しました。データベースはOracle 11gインスタンスですが、現時点では不明です。私はOS X 10.6.8でPython 2.6.1を使用しています(これはPythonのシステムバージョンです)。sourceforge.netからダウンロードしたcx-Oracleドライバモジュールバージョン5.1を使用しています。これは、virtualenv 1.6.1インスタンスサイトパッケージが表示されます。cx-Oracleを使用してUnicodeを挿入できません

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でエンコードされたテキストであることがわかっているファイルを開き、その文字列を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を探して周り狩り始めたと私は

変更5.0.4から5.1
にsourceforge.netからダウンロードしたCX-OracleソースのHISTORY.TXTでこれを見つけました1)UNICODEモードのサポートを削除し、 Unicodeを通過させるために、 の文字列を渡すことができます。これは、NLS_LANG環境の値を使用して という文字列がOracleに渡されることを意味します。 Python 3.x同じように。これにより、UNICODEモードを使用して発見された問題 が削除され、Python 2.xで不要な の制限が取り除かれました。たとえば、接続文字列 やSQL文でUnicodeを使用できませんでした。 ...

私の仮定は、NLS_LANG環境変数が「ASCII」または何らかの同等に設定されているので、私はユニコードの正しい値であると考えている「AL32UTF8」にNLS_LANGを設定してみてください、と設定されていることです私の接続を作成する前に新しい値。

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を一緒に使用したことはありません。私はこの問題に取り組むのに2日間を費やしており、DBAグループに行く前に問題が何であるかをよりよく理解したいと思います。環境変数を設定する

おかげで、

答えて

14

は正しい方法ですが、「AL32UTF8は、」NLS_LANGの正しい値ではありません。 Oracleのインスタンスで使用されているNLS_LANGの正しい値を取得するには、

SELECT USERENV ('language') FROM DUAL 
+0

私のDBAからの回答がありました。私たちの11gR2インストールの場合、CHARACTER SETは 'WE8MSWIN1252'で、NATIONAL CHARACTER SETは 'AL16UTF16'です。ドライバは、上記の変数のエンコーディングセットを正しく検出していないようです。どちらの場合も、接続の 'encoding'属性と 'nencoding'属性が「US-ASCII」であることを確認すると正しくありません。 NLS_LANGを 'AL16UTF16'にしようとすると、同じDatabaseErrorが得られます。なぜなら、スキーマへの接続が削除されているからです(そして実稼働環境にもあります)。なぜこれらのファイルにアクセスできないのかを説明します。 – snarkyname77

+0

私の状況では、上記のクエリの結果は "AMERICAN_AMERICA.US7ASCII"です。しかし、NLS_LANGが "_.AL32UTF8"(引用符なし)に設定されると、私のUnicode挿入が正しく動作するようになりました。 – davidjb

+0

上記のクエリの結果はAMERICAN_AMERICA.WE8MSWIN1252です。 @davidjb、どうやってその値を引用符なしに設定しますか?あなたはそれを得るためにあなたのスコープに何をインポートしましたか? – ThatAintWorking

関連する問題