Tôi có thể nhớ đã gặp phải loại vấn đề ngu ngốc này khi sử dụng trình điều khiển odbc, ngay cả khi lần đó là kết hợp java + oracle.
Điều cốt lõi là trình điều khiển odbc rõ ràng mã hóa chuỗi truy vấn khi gửi nó đến DB. Ngay cả khi trường là Unicode và nếu bạn cung cấp Unicode, trong một số trường hợp, nó dường như không thành vấn đề.
Bạn cần đảm bảo rằng những gì được gửi bởi trình điều khiển có cùng mã hóa với Cơ sở dữ liệu của bạn (không chỉ máy chủ mà còn cả cơ sở dữ liệu). Nếu không, tất nhiên bạn sẽ nhận được các ký tự vui nhộn vì máy khách hoặc máy chủ đang trộn lẫn mọi thứ khi mã hóa / hoặc giải mã. Bạn có bất kỳ ý tưởng nào về bộ ký tự (điểm mã như MS muốn nói) mà máy chủ của bạn đang sử dụng làm mặc định để giải mã dữ liệu không?
Đối chiếu không liên quan gì đến vấn đề này :)
Xem trang MS đó Ví dụ. Đối với các trường Unicode, đối chiếu chỉ được sử dụng để xác định thứ tự sắp xếp trong cột, không để chỉ định cách dữ liệu được lưu trữ.
Nếu bạn lưu trữ dữ liệu của mình dưới dạng Unicode, có một cách duy nhất để biểu diễn nó, đó là mục đích của Unicode:không cần xác định bộ ký tự tương thích với tất cả các ngôn ngữ mà bạn sẽ sử dụng :)
Câu hỏi ở đây là "điều gì sẽ xảy ra khi tôi cung cấp dữ liệu cho máy chủ mà không Unicode? ". Ví dụ:
- Khi tôi gửi một chuỗi UTF-8 tới máy chủ, nó sẽ hiểu nó như thế nào?
- Khi tôi gửi một chuỗi UTF-16 đến máy chủ, nó sẽ hiểu nó như thế nào?
- Khi tôi gửi một chuỗi Latin1 tới máy chủ, nó sẽ hiểu nó như thế nào?
Từ góc độ máy chủ, cả 3 chuỗi này chỉ là một dòng byte. Máy chủ không thể đoán mã hóa mà bạn đã mã hóa chúng. Có nghĩa là bạn sẽ gặp sự cố nếu ứng dụng khách odbc của bạn kết thúc gửi bytestrings (một chuỗi được mã hóa) tới máy chủ thay vì gửi unicode dữ liệu:nếu bạn làm như vậy, máy chủ sẽ sử dụng mã hóa được xác định trước (đó là câu hỏi của tôi:máy chủ sẽ sử dụng mã hóa nào? Vì nó không phải là đoán, nó phải là một giá trị tham số) và nếu chuỗi đã được mã hóa bằng cách sử dụng mã hóa khác, dzing , dữ liệu sẽ bị hỏng.
Nó hoàn toàn tương tự như làm trong Python:
uni = u'Hey my name is André'
in_utf8 = uni.encode('utf-8')
# send the utf-8 data to server
# send(in_utf8)
# on server side
# server receives it. But server is Japanese.
# So the server treats the data with the National charset, shift-jis:
some_string = in_utf8 # some_string = receive()
decoded = some_string.decode('sjis')
Hãy thử nó. Nó vui. Chuỗi được giải mã được cho là "Này tên tôi là André", nhưng là "Này tên tôi là Andr テ ゥ". é được thay thế bằng tiếng Nhật テ ゥ
Do đó, gợi ý của tôi:bạn cần đảm bảo rằng pyodbc có thể gửi trực tiếp dữ liệu dưới dạng Unicode. Nếu pyodbc không làm được điều này, bạn sẽ nhận được kết quả không mong muốn.
Và tôi đã mô tả vấn đề theo cách từ Máy khách đến Máy chủ. Nhưng cùng một loại vấn đề có thể phát sinh khi giao tiếp từ Máy chủ đến Máy khách. Nếu Khách hàng không thể hiểu dữ liệu Unicode, bạn có thể gặp rắc rối.
FreeTDS xử lý Unicode cho bạn.
Trên thực tế, FreeTDS sẽ lo mọi thứ cho bạn và dịch tất cả dữ liệu sang unicode UCS2. ( Nguồn ).
- Máy chủ <--> FreeTDS:Dữ liệu UCS2
- FreeTDS <--> pyodbc:chuỗi được mã hóa, được mã hóa bằng UTF-8 (từ
/etc/freetds/freetds.conf
)
Vì vậy, tôi hy vọng ứng dụng của bạn hoạt động chính xác nếu bạn chuyển dữ liệu UTF-8 sang pyodbc. Trên thực tế, như vé django-pyodbc này trạng thái, django-pyodbc giao tiếp trong UTF-8 với pyodbc, vì vậy bạn sẽ ổn.
TDS miễn phí 0,82
Tuy nhiên, cramm0 nói rằng FreeTDS 0.82 không hoàn toàn không có lỗi và có sự khác biệt đáng kể giữa 0.82 và phiên bản 0.82 được vá chính thức có thể được tìm thấy tại đây . Bạn có thể nên thử sử dụng FreeTDS đã được vá
Đã chỉnh sửa : đã xóa dữ liệu cũ, không liên quan gì đến FreeTDS mà chỉ liên quan đến trình điều khiển odbc thương mại của Easysoft. Xin lỗi.