sql >> Base de Datos >  >> RDS >> Sqlserver

usando pyodbc en linux para insertar caracteres unicode o utf-8 en un campo nvarchar mssql

Puedo recordar haber tenido este tipo de problemas estúpidos al usar controladores odbc, incluso si esa vez era una combinación de java+oracle.

Lo principal es que el controlador odbc aparentemente codifica la cadena de consulta cuando la envía a la base de datos. Incluso si el campo es Unicode y proporciona Unicode, en algunos casos parece no importar.

Debe asegurarse de que lo que envía el controlador tenga la misma codificación que su base de datos (no solo el servidor, sino también la base de datos). De lo contrario, por supuesto, obtienes caracteres funky porque el cliente o el servidor están mezclando cosas al codificar o decodificar. ¿Tiene alguna idea del juego de caracteres (punto de código, como le gusta decir a MS) que su servidor está usando como predeterminado para decodificar datos?

La intercalación no tiene nada que ver con este problema :)

Consulte esa página de MS por ejemplo. Para los campos Unicode, la intercalación se usa solo para definir el orden de clasificación en la columna, no para especificar cómo se almacenan los datos.

Si almacena sus datos como Unicode, hay una forma única de representarlos, ese es el propósito de Unicode:no es necesario definir un juego de caracteres que sea compatible con todos los idiomas que va a usar :)

La pregunta aquí es "¿qué sucede cuando doy datos al servidor que no ¿Unicode?". Por ejemplo:

  • Cuando envío una cadena UTF-8 al servidor, ¿cómo la entiende?
  • Cuando envío una cadena UTF-16 al servidor, ¿cómo la entiende?
  • Cuando envío una cadena Latin1 al servidor, ¿cómo la entiende?

Desde la perspectiva del servidor, todas estas 3 cadenas son solo una secuencia de bytes. El servidor no puede adivinar la codificación en la que los codificaste. Lo que significa que podrás tener problemas si su cliente odbc termina enviando cadenas de bytes (una cadena codificada) al servidor en lugar de enviar unicode datos:si lo hace, el servidor usará una codificación predefinida (esa era mi pregunta:¿qué codificación usará el servidor? Como no es adivinar, debe ser un valor de parámetro), y si la cadena se codificó usando un codificación diferente, dzing , los datos se corromperán.

Es exactamente similar a hacerlo en 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')

Solo inténtalo. Es divertido. Se supone que la cadena decodificada es "Hola, mi nombre es André", pero es "Hola, mi nombre es André". é es reemplazado por japonés テゥ

De ahí mi sugerencia:debe asegurarse de que pyodbc pueda enviar directamente los datos como Unicode. Si pyodbc no logra hacer esto, obtendrá resultados inesperados.

Y describí el problema de la manera Cliente a Servidor. Pero el mismo tipo de problemas pueden surgir cuando se comunica desde el servidor al cliente. Si el Cliente no puede comprender los datos Unicode, es probable que tenga problemas.

FreeTDS maneja Unicode por usted.

En realidad, FreeTDS se encarga de las cosas por usted y traduce todos los datos a UCS2 Unicode. (Fuente ).

  • Servidor <--> FreeTDS:datos UCS2
  • FreeTDS <--> pyodbc :cadenas codificadas, codificadas en UTF-8 (de /etc/freetds/freetds.conf )

Por lo tanto, espero que su aplicación funcione correctamente si pasa datos UTF-8 a pyodbc. De hecho, como este ticket django-pyodbc estados, django-pyodbc se comunica en UTF-8 con pyodbc, por lo que debería estar bien.

TDS libre 0.82

Sin embargo, cramm0 dice que FreeTDS 0.82 no está completamente libre de errores y que existen diferencias significativas entre 0.82 y la versión 0.82 parcheada oficial que se puede encontrar aquí . Probablemente debería intentar usar el FreeTDS parcheado

Editado :eliminó los datos antiguos, que no tenían nada que ver con FreeTDS pero solo eran relevantes para el controlador odbc comercial de Easysoft. Lo siento.