Quiero establecer una variable de cadena Unicode en un carácter particular en función de su punto de código Unicode.
Quiero usar un punto de código más allá de 65535, pero la base de datos SQL Server 2008 R2 tiene una clasificación de SQL_Latin1_General_CP1_CI_AS
.
Según la documentación de NCHAR de Microsoft , la NCHAR
función toma un número entero de la siguiente manera:
entero_expresión
Cuando la clasificación de la base de datos no contiene el indicador de caracteres suplementarios (SC), este es un número entero positivo de 0 a 65535 (0 a 0xFFFF). Si se especifica un valor fuera de este rango, se devuelve NULL. Para obtener más información sobre los caracteres adicionales, consulte Compatibilidad y compatibilidad con Unicode.
Cuando la clasificación de la base de datos admite el indicador de caracteres suplementarios (SC), este es un número entero positivo de 0 a 1114111 (0 a 0x10FFFF). Si se especifica un valor fuera de este rango, se devuelve NULL.
Entonces este código:
SELECT NCHAR(128512);
Devoluciones NULL
en esta base de datos.
Me gustaría que devuelva lo mismo que esto:
SELECT N'😀';
¿Cómo puedo establecer una variable de cadena Unicode (por ejemplo, nvarchar) en un emoji usando el código (sin usar el carácter emoji real) en una base de datos donde la clasificación "no contiene el indicador de caracteres suplementarios (SC)"?
Lista completa de puntos de código emoji Unicode
(En última instancia, quiero que funcione cualquier personaje. Simplemente elegí emoji para facilitar la referencia).
(Aunque el servidor es SQL Server 2008 R2, también tengo curiosidad sobre las soluciones para versiones posteriores).
Suponiendo que no hay forma, ¿podría hacer referencia a una función definida por el usuario en línea en otra base de datos que tuviera una clasificación adecuada?
¿Cómo encuentro una clasificación que tenga la bandera de "carácter suplementario"?
Esto no devuelve ningún registro en nuestro servidor:
SELECT * FROM sys.fn_helpcollations()
WHERE name LIKE 'SQL%[_]SC';
Parece Latin1_General_100_CI_AS_SC
que se introdujo SQL Server 2012, que funcionaría. ¿Se pueden instalar intercalaciones en instancias anteriores?
Recopilación de referencias:
- Respuesta a ¿Cuál es la diferencia entre char, nchar, varchar y nvarchar en SQL Server?
- Información de cotejo de caracteres suplementarios de Microsoft
- Lista de clasificación de SQL Server 2008 R2 de Microsoft
¿Existe una explicación de por qué, independientemente de la intercalación, SQL Server puede comprender y tratar los caracteres extendidos, excepto desde la perspectiva de NCHAR
?
Respuestas:
La codificación UCS-2 siempre es de 2 bytes por carácter y tiene un rango de 0 - 65535 (0x0000 - 0xFFFF). UTF-16 (independientemente de Big Endian o Little Endian) tiene un rango de 0 - 1114111 (0x0000 - 0x10FFFF). El rango 0 - 65535 / 0x0000 - 0xFFFF de UTF-16 es de 2 bytes por carácter, mientras que el rango superior a 65536 / 0xFFFF es de 4 bytes por carácter.
Windows y SQL Server comenzaron usando la codificación UCS-2 porque estaba disponible y UTF-16 aún no se había finalizado. Afortunadamente, sin embargo, hubo suficiente previsión puesta en los diseños de UCS-2 y UTF-16 para que las asignaciones de UCS-2 sean un subconjunto completo de las asignaciones de UTF-16 (es decir: el rango 0 - 65535 / 0x0000 - 0xFFFF de UTF-16 es UCS-2). Y, el rango 65536-1114111 (0x10000 - 0x10FFFF) de UTF-16 se construye a partir de dos puntos de código en el rango UCS-2 (rangos 0xD800 - 0xDBFF y 0xDC00 - 0xDFFF, específicamente) que se reservaron para este propósito y de lo contrario no tienen sentido. Esta combinación de dos puntos de código se conoce como un par sustituto, y los pares sustitutos representan caracteres más allá del rango UCS-2 que se conocen como caracteres suplementarios.
Toda esa información explica dos aspectos de los
NVARCHAR
datos / Unicode en SQL Server:NCHAR()
) no manejan pares sustitutos / caracteres suplementarios cuando no se utiliza una clasificación complementaria con reconocimiento de caracteres (SCA; es decir, una con_SC
, o_140_
no_BIN*
en el nombre) porque las clasificaciones no SCA (especialmente lasSQL_
Las colaciones) se implementaron originalmente antes de que se completara UTF-16 (en algún momento del año 2000, creo). Las noSQL_
intercalaciones que tienen_90_
o_100_
en sus nombres pero no_SC
tienen soporte mínimo para caracteres suplementarios en términos de comparación y clasificación.NVARCHAR
/NCHAR
/XML
/NTEXT
porque UCS-2 y UTF-16 son exactamente las mismas secuencias de bytes. La única diferencia es que UTF-16 utiliza los puntos de código sustituto para construir pares sustitutos, y UCS-2 simplemente no puede asignarlos a ningún carácter, por lo tanto, aparecen en las funciones integradas como dos caracteres desconocidos.Con esa información de fondo en mente, ahora podemos pasar por las preguntas específicas:
Eso solo puede suceder si la base de datos actual, donde se ejecuta la consulta, tiene una clasificación predeterminada que es compatible con los caracteres suplementarios, y se introdujeron en SQL Server 2012. Las funciones integradas que tienen parámetros de entrada de cadena pueden tener la clasificación proporcionada en línea a través de la
COLLATE
cláusula (es decirLEN(N'string' COLLATE Some_Collation_SC)
) y no es necesario que se ejecute dentro de una base de datos que tenga una clasificación predeterminada de SCA. Sin embargo, las funciones integradas, comoNCHAR()
aceptar unINT
parámetro de entrada y laCOLLATE
cláusula no son válidas en ese contexto (es por eso queNCHAR()
solo admite caracteres suplementarios cuando la base de datos actual tiene una clasificación predeterminada que es compatible con caracteres suplementarios; pero esto es innecesario inconveniente que se puede cambiar, así que vote por mi sugerencia:La función NCHAR () siempre debe devolver caracteres suplementarios para los valores 0x10000 - 0x10FFFF independientemente de la clasificación predeterminada de la base de datos activa ).Cómo SQL Server puede almacenar y recuperar caracteres suplementarios sin pérdida de datos se explicó en la sección superior de esta respuesta. Pero no es cierto que
NCHAR
sea la única función incorporada que tiene problemas con los caracteres suplementarios (cuando no se utiliza una intercalación SCA). Por ejemplo,LEN(N'😀' COLLATE SQL_Latin1_General_CP1_CI_AS)
devuelve un valor de 2 mientras queLEN(N'😀' COLLATE Latin1_General_100_CI_AS_SC)
devuelve un valor de 1.Si va al segundo enlace publicado en la Pregunta (es decir, "Información de cotejo de caracteres suplementarios de Microsoft") y se desplaza un poco hacia abajo, verá un gráfico de las funciones integradas y cómo se comportan en función del cotejo efectivo.
En una versión de SQL Server anterior a 2012 no puede. Pero, comenzando con SQL Server 2012, puede usar la siguiente consulta:
Su consulta estaba cerca, pero el patrón comenzó
SQL
y las Colaciones de SQL Server (es decir, las que comienzan conSQL_
) han quedado en desuso por un tiempo a favor de las Colaciones de Windows (las que no comienzan conSQL_
). Por lo tanto, lasSQL_
intercalaciones no se actualizan y, por lo tanto, no tienen versiones más nuevas que incluirían la_SC
opción (y a partir de SQL Server 2017, todas las nuevas intercalaciones admiten automáticamente caracteres suplementarios y no necesitan o tienen el_SC
indicador; y sí, la consulta que se muestra inmediatamente arriba explica eso, así como recoger las_UTF8
intercalaciones agregadas en SQL Server 2019).No, no puede instalar intercalaciones en una versión anterior de SQL Server.
Cuando no use una Clasificación SCA, puede inyectar Puntos de Código superiores a 65535 / U + FFFF de dos maneras:
NCHAR()
función, cada una con una parte del parVARBINARY
forma de la secuencia de bytes Little Endian (es decir, invertida).Estos dos métodos para insertar caracteres suplementarios / pares sustitutos funcionarán incluso si la intercalación efectiva es compatible con los caracteres suplementarios, y deberían funcionar igual en todas las versiones de SQL Server, al menos desde 2005 (aunque probablemente también funcionaría en SQL Server 2000 también).
Ejemplo:
💩
ACTUALIZAR
Puede usar el siguiente iTVF para obtener los valores de Par sustituto (en ambos
INT
y enBINARY
forma) desde cualquier Punto de código entre 65536 - 1114111 (0x010000 - 0x10FFFF). Y, aunque el parámetro de entrada es de tipoINT
, puede pasar en la forma binaria / hexadecimal del Punto de código y se convertirá implícitamente al valor entero correcto.Usando la función anterior, las siguientes dos consultas:
ambos devuelven lo siguiente:
ACTUALIZACIÓN 2: ¡Una actualización aún mejor!
He adaptado el iTVF que se muestra arriba para que ahora devuelva 188,657 puntos de código para que no tenga que ajustar ningún valor en particular. Por supuesto, al ser un TVF, puede agregar una
WHERE
cláusula para filtrar en un punto de código particular, o rango de puntos de código, o "caracteres similares", etc. Y, incluye columnas adicionales con secuencias de escape preformateadas para construir cada código punto (BMP y caracteres suplementarios) en T-SQL, HTML y estilo C (es decir\xHHHH
). Lea todo sobre esto aquí:Consejo SSMS # 3: Acceda / investigue fácilmente TODOS los caracteres Unicode (Sí, incluidos los Emojis 😸)
fuente