2013-01-09 22 views
15

Tôi gặp sự cố khi chèn unicode vào một lược đồ Oracle, tôi nghĩ cơ sở dữ liệu là một cá thể Oracle 11g nhưng không chắc chắn vào thời điểm này. Tôi đang sử dụng python 2.6.1 trên OS X 10.6.8 (đây là hệ thống verison của python) và đang sử dụng mô-đun trình điều khiển cx-Oracle phiên bản 5.1 được tải xuống từ sourceforge.net, được xây dựng và cài đặt cho phiên bản virtualenv 1.6.1 với các gói trang web hiển thị. Tập lệnh của tôi như sauKhông thể chèn Unicode Sử dụng cx-Oracle

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) 

Tôi tạo một kết nối để tạo bảng thử nghiệm với trường id và văn bản loại NUMBER và NCLOB. Tôi mở một tệp có chứa những gì tôi biết là văn bản được mã hóa bằng UTF-8, giải mã chuỗi thành unicode. Tạo một đoạn mã chèn trong một chuỗi unicode và thực thi câu lệnh đó, và kết quả là lỗi này.

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) 

Có gì đó đang cố gắng mã hóa câu lệnh của tôi dưới dạng ASCII trước khi chèn nó vào lược đồ Oracle. Vì vậy, tôi bắt đầu săn bắn xung quanh tìm cách để hiểu rõ hơn về cx-Oracle xử lý như thế nào unicode và thấy điều này trong HISTORY.txt của nguồn cx-Oracle tôi tải về từ sourceforge.net

Thay đổi từ 5.0.4 đến 5.1
1) Xóa hỗ trợ cho chế độ UNICODE và cho phép Unicode được chuyển qua trong ở khắp mọi nơi mà một chuỗi có thể được truyền vào. Điều này có nghĩa là các chuỗi sẽ là được chuyển đến Oracle bằng cách sử dụng giá trị của môi trường NLS_LANG biến trong Python 3.x cũng. Làm điều này loại bỏ một loạt các vấn đề được phát hiện bằng cách sử dụng chế độ UNICODE và cũng loại bỏ một hạn chế không cần thiết trong Python 2.x mà Unicode không thể được sử dụng trong chuỗi kết nối hoặc câu lệnh SQL. ...

giả định của tôi là biến môi trường NLS_LANG được thiết lập để 'ascii' hoặc một số tương đương, vì vậy tôi cố gắng thiết lập NLS_LANG để 'AL32UTF8' mà tôi tin là giá trị chính xác cho unicode, và thiết lập giá trị mới trước khi tạo kết nối của tôi.

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

Nhưng tôi gặp phải lỗi này.

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 

Vì vậy, có vẻ như tôi không thể giả mạo giá trị NLS_LANG.

Dưới đây là các câu hỏi của tôi kể từ bây giờ. Tôi thiếu một cái gì đó đơn giản như một loại cột không chính xác? Vấn đề với trình điều khiển cx-Oracle? Tôi có cần phải đặt biến môi trường "WITH_UNICODE" khi xây dựng mô-đun cx-Oracle không và tôi sẽ làm như thế nào? Vấn đề với phiên bản Oracle? Tôi có ít kinh nghiệm với Oracle và chưa bao giờ làm việc với Oracle và python cùng nhau. Tôi đã dành hai ngày làm việc về vấn đề này và muốn hiểu rõ hơn về vấn đề là gì trước khi tôi đi đến nhóm DBA.

Cảm ơn,

Trả lời

14

Biến môi trường thiết lập là đúng cách, nhưng "AL32UTF8" không phải là giá trị phù hợp cho NLS_LANG. Để có được giá trị bên phải của NLS_LANG sử dụng trong trường hợp bạn của Oracle, thực hiện

SELECT USERENV ('language') FROM DUAL 
+0

Cảm ơn bạn đã trả lời, cuối cùng tôi nhận được phản hồi từ các DBA của tôi.Để cài đặt 11gR2, BỘ ĐOẠN CHARACTER là 'WE8MSWIN1252' và BỘ ĐOẠN QUỐC GIA là 'AL16UTF16'. Dường như trình điều khiển không phát hiện được bộ mã hóa trong các biến ở trên một cách chính xác. Kiểm tra thuộc tính 'mã hóa' và 'nencoding' trên kết nối mang lại 'US-ASCII' trong cả hai trường hợp không chính xác. Tôi vẫn nhận được cùng một DatabaseError khi cố gắng NLS_LANG đến 'AL16UTF16', vì kết nối của tôi với lược đồ sẽ bị loại bỏ (và cũng sẽ được sản xuất) giải thích tại sao những tệp đó không thể truy cập được. – snarkyname77

+0

Trong trường hợp của tôi, kết quả của tôi từ truy vấn trên là "AMERICAN_AMERICA.US7ASCII". Tuy nhiên, chèn Unicode của tôi bắt đầu hoạt động chính xác khi NLS_LANG của tôi được đặt thành "_.AL32UTF8" (không có dấu ngoặc kép). – davidjb

+0

Kết quả của tôi từ truy vấn trên là AMERICAN_AMERICA.WE8MSWIN1252. @ davidjb, làm thế nào để bạn đặt nó vào giá trị đó mà không có dấu ngoặc kép. Bạn đã nhập vào phạm vi của bạn để có được nó? – ThatAintWorking

Các vấn đề liên quan