Problema de codificación con la columna VARCHAR de SQL Server recuperada en Python

10

Recientemente tuvimos un problema con la codificación relacionada con un campo que se almacena como varchar (120) en SQL Server. En SSMS, el varchar aparece como:

"¿Quién mató a JonBen?"

Sin embargo, cuando se lleva a Python, aparece como:

ingrese la descripción de la imagen aquí

He investigado esto desde el lado de Python, y no pasa nada extraño. Mi teoría es que el varchar en SQL Server está aceptando caracteres UTF-8 que se muestran de manera diferente en python que SSMS. No estoy muy familiarizado con la codificación en SQL Server. ¿Puede alguien decirme lo siguiente?

  • ¿Hay alguna manera en SSMS para ver la codificación de varchar? Por ejemplo, vea \ x82 en lugar de mostrar la coma como es actualmente de SSMS?
  • Estamos usando SQL Server 2008. ¿Hay alguna forma de cambiar la codificación de los caracteres UTF-8 a caracteres ASCII sin usar herramientas de importación / exportación o volcar en un archivo plano? Es decir, ¿puedo hacer esta conversión a través de una consulta?
  • ¿Hay alguna manera de identificar mediante programación los registros problemáticos a través de una consulta (la problemática se define como caracteres UTF-8 que no son compatibles a través de ASCII)?

¡Gracias de antemano!

Usando sp_help N'table_name';encontré que la intercalación de esta VARCHARcolumna es: SQL_Latin1_General_CP1_CI_AS.

Eric
fuente
¿Qué cotejo está VARCHARusando esa columna?
Solomon Rutzky
@SolomonRutzky, ¿cómo verificas la clasificación? No estoy seguro de lo que eso significa
Eric
La forma más rápida que pienso es: sp_help N'table_name';. Mire la columna basada en "nombre" y luego mire la columna "collation_name".
Solomon Rutzky
@SolomonRutzky la clasificación para ese campo es 'SQL_Latin1_General_CP1_CI_AS'
Eric

Respuestas:

17

SQL Server no almacena UTF-8 bajo ninguna circunstancia. Obtiene UTF-16 Little Endian (LE) a través de NVARCHAR(incluyendo NCHARy NTEXT, pero nunca usa NTEXT) y XML, o alguna codificación de 8 bits, basada en una página de códigos, a través de VARCHAR(incluyendo CHARy TEXT, pero nunca usa TEXT) .

El problema aquí es que su código está traduciendo mal ese carácter 0x82, pensando que es UTF-8, pero no lo es. No hay un "carácter" UTF-8 que tenga un valor de 0x82, por lo que se obtiene el símbolo "desconocido" / reemplazo de " ". Consulte la siguiente tabla UTF-8 que muestra que no hay caracteres para un solo byte de 0x82:

Tabla de codificación UTF-8

Según lo establecido por el OP, la clasificación de la columna en cuestión es SQL_Latin1_General_CP1_CI_AS, lo que significa que la codificación de 8 bits está utilizando la página de códigos 1252, que es Windows Latin 1 (ANSI) . Y verificar el valor del gráfico (desplazarse hacia abajo hasta el gráfico inferior, ya que tiene los nombres de los caracteres) 0x82 (busque "82" en la columna "Punto de código") es, de hecho, la marca de comillas baja-9 que ve en SSMS. Ese personaje, en UTF-8, es una secuencia de 3 bytes: E2 80 9A.

Lo que todo esto significa es: su código de Python necesita establecer la codificación del cliente para la conexión de SQL Server a la página de códigos 1252, o debe cambiar / convertir la codificación de la cadena devuelta de la página de códigos 1252 a UTF-8.

Por supuesto, si esto se muestra en una página web, entonces podría cambiar el juego de caracteres declarado de la página Windows-1252, pero eso podría interferir con otros caracteres en la página si ya hay caracteres UTF-8.

Solomon Rutzky
fuente
Bien, esto es muy útil, gracias Solomon. Por favor, hágamelo saber acerca de la traducción errónea. Este es un tema bastante complicado y ni siquiera estoy seguro de por dónde empezar.
Eric
¡Guau, detalle increíble, @Solomon! Llegué aquí buscando un problema diferente de Python + MS SQL, pero seguí leyendo porque estaba aprendiendo mucho. :-P
Mike Williamson
1
@ MikeWilliamson Gracias por compartir ese cumplido :). También podría estar interesado en lo siguiente: TSQL md5 hash diferente a C # .NET md5 (en SO), Cómo eliminar marcas de acento hebreo (aquí en DBA.SE) y Collations.Info . ¡Disfrutar!
Solomon Rutzky
¡Gracias! Sospecho que cualquiera que trabaje con un idioma no latino sabe esto mucho mejor que cualquiera de nosotros que trabaje felizmente en los Estados Unidos / Reino Unido. :)
Mike Williamson
1
Solo una nota: MS SQL Server 2019 presenta soporte nativo para UTF-8 en los tipos de datos VARCHAR / CHAR.
Gregory Arenius