El punto de código Unicode 9619 es un carácter llamado "Sombra oscura": ▓
( http://unicode-table.com/en/search/?q=9619 ).
Usando la SQL_Latin1_General_CP1_CI_AS
colación y la página de códigos 1252, esperaría que convertir / convertir ese carácter Unicode en un tipo de datos que no sea Unicode resultaría en un signo de interrogación ( ?
) ya que la página de códigos 1252 no parece contener este carácter y parece ser el SQL Server comportamiento cuando la conversión no puede tener lugar.
Entonces mi pregunta es: ¿por qué SQL Server convierte este carácter en un código ASCII 166 que es "Tubería, barra vertical rota" ¦
:?
SELECT NCHAR(9619), CAST(NCHAR(9619) AS CHAR(1)), ASCII(CAST(NCHAR(9619) AS CHAR(1)))
sql-server
collation
encoding
unicode
Henry Lee
fuente
fuente
Respuestas:
SQL Server no está empleando ninguna lógica personalizada especial aquí; está utilizando servicios estándar del sistema operativo para realizar la conversión.
Específicamente, el tipo de SQL Server y la expresión service (
sqlTsEs
) llama a la rutina del sistema operativoWideCharToMultiByte
enkernel32.dll
. SQL Server establece los parámetros de entrada paraWideCharToMultiByte
que la rutina realice una 'traducción rápida'. Esto es más rápido que solicitar que se use un carácter predeterminado específico cuando no existe una traducción directa.La traducción rápida se basa en la página de códigos de destino para realizar un mapeo que mejor se ajuste a los caracteres no coincidentes , como se menciona en el enlace que Martin Smith proporcionó en un comentario a la pregunta:
Cuando los parámetros de entrada se configuran para una traducción rápida,
WideCharToMultiByte
llama al servicio del sistema operativoGetMBNoDefault
( fuente ). La inspección de la pila de llamadas de SQL Server al realizar la conversión especificada en la pregunta confirma esto:fuente
La conversión de datos Unicode a una página de códigos particular emplea lo que se conoce como la estrategia de "Mejor ajuste" (como se señala en la respuesta de @ Paul y en el enlace que @Martin señaló en un comentario sobre la Pregunta). De acuerdo con esa página de MSDN para la codificación de caracteres en .NET Framework :
Pero, ¿qué son exactamente estas asignaciones? Esa página de MSDN solía decir lo siguiente:
Sin embargo, eso no era del todo correcto. Quizás las "estrategias" para determinar los mapeos no están exactamente documentadas. Okay. Pero, las asignaciones en sí están documentadas, pero no en los lugares más fáciles de encontrar.
Entonces, gracias a que Microsoft movió la documentación a GitHub, esa página ahora dice lo siguiente (porque lo actualicé):
Si va a la siguiente URL, verá una lista de varios archivos, cada uno con el nombre de la página de códigos a la que asigna los caracteres Unicode:
ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/
La mayoría de los archivos se actualizaron por última vez (o al menos se colocaron allí) el 04/10/2006, y uno de ellos se actualizó el 14/03/2012. La primera parte de esos archivos asigna códigos ASCII en un punto de código Unicode equivalente. Pero la segunda parte de cada archivo asigna los caracteres Unicode a sus "equivalentes" ASCII.
Escribí un script de prueba que usa las asignaciones de la página de códigos 1252 para verificar si SQL Server realmente está usando esas asignaciones. Eso se puede determinar respondiendo estas dos preguntas:
?
"?El script de prueba es demasiado largo para colocarlo aquí, así que lo publiqué en Pastebin en:
Asignaciones de Unicode a la página de códigos en SQL Server
La ejecución del script mostrará que la respuesta a la primera pregunta anterior es "Sí" (lo que significa que se cumplen todas las asignaciones proporcionadas). También mostrará que la respuesta a la segunda pregunta es "No" (lo que significa que ninguno de los Puntos de código no asignados se convierte en otra cosa que no sea el carácter "desconocido"). Por lo tanto, ese archivo de mapeo es muy preciso :-).
fuente