Lembro-me de ter esse tipo de problema estúpido usando drivers odbc, mesmo que naquela época fosse uma combinação java + oracle.
O principal é que o driver odbc aparentemente codifica a string de consulta ao enviá-la para o banco de dados. Mesmo que o campo seja Unicode, e se você fornecer Unicode, em alguns casos isso não parece importar.
Você precisa garantir que o que é enviado pelo driver tenha a mesma codificação do seu Banco de Dados (não apenas servidor, mas também banco de dados). Caso contrário, é claro que você obtém caracteres estranhos porque o cliente ou o servidor estão misturando as coisas ao codificar/ou decodificar. Você tem alguma idéia do charset (codepoint como MS gosta de dizer) que seu servidor está usando como padrão para decodificar dados?
O agrupamento não tem nada a ver com este problema :)
Consulte essa página MS por exemplo. Para campos Unicode, o agrupamento é usado apenas para definir a ordem de classificação na coluna, não para especificar como os dados são armazenados.
Se você armazena seus dados como Unicode, existe uma maneira única de representá-los, esse é o propósito do Unicode:não há necessidade de definir um charset compatível com todos os idiomas que você usará :)
A questão aqui é "o que acontece quando eu dou dados para o servidor que não Unicode?". Por exemplo:
- Quando eu envio uma string UTF-8 para o servidor, como ele a entende?
- Quando envio uma string UTF-16 para o servidor, como ele a entende?
- Quando envio uma string Latin1 para o servidor, como ele a entende?
Do ponto de vista do servidor, todas essas 3 strings são apenas um fluxo de bytes. O servidor não pode adivinhar a codificação na qual você os codificou. O que significa que você vai ter problemas se o seu cliente odbc acabar enviando bytestrings (uma string codificada) para o servidor em vez de enviar unicode data:se você fizer isso, o servidor usará uma codificação predefinida (essa foi a minha pergunta:qual codificação o servidor usará? Como não é adivinhação, deve ser um valor de parâmetro), e se a string foi codificada usando um codificação diferente, dzing , os dados serão corrompidos.
É exatamente semelhante a fazer em 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')
Apenas tente. É divertido. A string decodificada deveria ser "Ei, meu nome é André", mas é "Ei, meu nome é Andrテゥ". é é substituído pelo japonês テゥ
Daí minha sugestão:você precisa garantir que o pyodbc seja capaz de enviar os dados diretamente como Unicode. Se o pyodbc não fizer isso, você obterá resultados inesperados.
E eu descrevi o problema da maneira Cliente para Servidor. Mas o mesmo tipo de problema pode surgir ao se comunicar de volta do Servidor para o Cliente. Se o cliente não puder entender os dados Unicode, você provavelmente terá problemas.
O FreeTDS lida com Unicode para você.
Na verdade, o FreeTDS cuida das coisas para você e traduz todos os dados para unicode UCS2. (Fonte ).
- Servidor <--> FreeTDS:dados UCS2
- FreeTDS <--> pyodbc :strings codificadas, codificadas em UTF-8 (de
/etc/freetds/freetds.conf
)
Portanto, espero que seu aplicativo funcione corretamente se você passar dados UTF-8 para pyodbc. Na verdade, como este tíquete django-pyodbc estados, django-pyodbc se comunica em UTF-8 com pyodbc, então você deve estar bem.
FreeTDS 0.82
No entanto, cramm0 diz que o FreeTDS 0.82 não é completamente livre de bugs e que existem diferenças significativas entre 0.82 e a versão oficial 0.82 corrigida que pode ser encontrada aqui . Você provavelmente deve tentar usar o FreeTDS corrigido
Editado :removidos os dados antigos, que não tinham nada a ver com o FreeTDS, mas eram relevantes apenas para o driver odbc comercial da Easysoft. Desculpe.