¿Cómo funciona la intercalación entre mayúsculas y minúsculas?

19

El tipo de intercalación predeterminado en SQL Server permite la indexación contra cadenas que no distinguen entre mayúsculas y minúsculas, pero el caso de los datos persiste. ¿Cómo funciona esto realmente? Estoy buscando las tuercas y tornillos reales, bits y bytes, o un buen recurso que lo explique en detalle.

create table casetest (fruitnames nvarchar(50) not null);
create unique index IX_fruitnames on casetest(fruitnames);

insert into casetest values ('apples');
insert into casetest values ('Pears');
-- this insert fails
insert into casetest values ('pears');

-- this yields 'Pears' as a result
select * from casetest (forceseek) where fruitnames = 'PEARS'

update casetest set fruitnames = 'pears' where fruitnames = 'pEArs'

-- this yields 'pears' as a result
select * from casetest (forceseek) where fruitnames = 'PEARS'

Las preguntas sobre las intercalaciones de SQL Server que Robert Sheldon le hizo preguntar demasiado sobre cómo utilizar la intercalación. No cubre cómo funciona la colación. Estoy interesado en cómo se puede crear / consultar eficientemente un índice sin preocuparse por el caso, mientras se almacenan simultáneamente los datos del caso.

cocogorilla
fuente
1
Puede consultar de manera eficiente (por ejemplo, utilizando una búsqueda de índice) cadenas sin distinción entre mayúsculas y minúsculas en un campo sensible a mayúsculas y minúsculas, pero es un poco molesto .
John Eisbrener
cocogorilla: vea la nota n. ° 1 que acabo de agregar al final de mi respuesta con respecto a la clasificación "predeterminada".
Solomon Rutzky

Respuestas:

26

indexación contra cadenas que no distinguen entre mayúsculas y minúsculas, pero el caso de los datos persiste. ¿Cómo funciona esto realmente?

En realidad, este no es un comportamiento específico de SQL Server, es simplemente cómo funcionan estas cosas en general.

Entonces, los datos son los datos. Si usted está hablando de un índice concreto, los datos debe ser almacenado, ya que es otra cosa sería necesaria una consulta en la tabla principal cada vez para obtener el valor real, y no habría ninguna posibilidad de un índice de cobertura (en al menos no para los tipos de cadena).

Los datos, ya sea en la tabla / índice agrupado o en el índice no agrupado, no contienen ninguna información de clasificación / clasificación. Es simplemente datos. La intercalación (reglas y sensibilidades locales / culturales) son solo metadatos adjuntos a la columna y se usan cuando se llama a una operación de clasificación (a menos que sea anulada por unCOLLATEcláusula), que incluiría la creación / reconstrucción de un índice. Las reglas definidas por una intercalación no binaria se utilizan para generar claves de clasificación, que son representaciones binarias de la cadena (las claves de clasificación no son necesarias en las intercalaciones binarias). Estas representaciones binarias incorporan todas las reglas locales / culturales y sensibilidades seleccionadas. Las claves de clasificación se utilizan para colocar los registros en su orden correcto, pero no se almacenan en el índice o la tabla. No están almacenados (al menos no he visto estos valores en el índice y me dijeron que no están almacenados) porque:

  1. No son realmente necesarios para la clasificación, ya que de todos modos estarían simplemente en el mismo orden que las filas de la tabla o índice. Pero, el orden físico del índice es solo ordenar, no comparar.
  2. Si bien almacenarlos podría hacer que las comparaciones sean más rápidas, también aumentaría el índice, ya que el tamaño mínimo para un solo carácter es de 5 bytes, y eso es solo "sobrecarga" (de la estructura de la clave de clasificación). La mayoría de los caracteres son de 2 bytes cada uno, más 1 byte si hay acento, más 1 byte si está en mayúscula. Por ejemplo, "e" es una clave de 7 bytes, "E" y "é" son 8 bytes, y "É" es una clave de 9 bytes. Por lo tanto, no vale la pena almacenarlos al final.

Hay dos tipos de intercalaciones: SQL Server y Windows.

servidor SQL

Las intercalaciones de SQL Server (aquellas con nombres que comienzan con SQL_) son la forma anterior de clasificación / comparación anterior a SQL Server 2000 (aunque todavíaSQL_Latin1_General_CP1_CI_AS es la instalación predeterminada en los sistemas operativos de inglés de EE. UU., Por desgracia). En este modelo anterior, simplista y no Unicode, cada combinación de configuración regional, página de códigos y las diversas sensibilidades reciben una asignación estática de cada uno de los caracteres en esa página de códigos. A cada personaje se le asigna un valor (es decir, clasificar el peso) para indicar cómo se compara con los demás. Las comparaciones en este modelo parecen hacer una operación de dos pasos:

  1. Primero, elimina todos los acentos (de modo que "  ü  " se convierte en "  u  "), expande caracteres como "  Æ  " en "  A  " y "  E  ", luego realiza una ordenación inicial para que las palabras estén en un orden natural (cómo lo haría Espere encontrarlos en un diccionario).
  2. Luego, va carácter por carácter para determinar la igualdad en función de estos valores subyacentes por cada carácter. Esta segunda parte es lo que describe Mustaccio en su respuesta .

Las únicas sensibilidades que se pueden ajustar en estas intercalaciones son: "mayúsculas y minúsculas" ("ancho", "tipo kana" y "selector de variación" no están disponibles). Además, ninguna de estas colaciones admite caracteres suplementarios (lo cual tiene sentido ya que son específicos de Unicode y estas colaciones solo se aplican a datos que no son Unicode).

Este enfoque se aplica solo a VARCHARdatos que no son Unicode . Cada combinación única de configuración regional, página de códigos, mayúsculas y minúsculas tiene una "ID de clasificación" específica, que puede ver en el siguiente ejemplo:

SELECT COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CI_AS', 'SortID'), -- 52
       COLLATIONPROPERTY(N'SQL_Latin1_General_CP1_CS_AS', 'SortID'), -- 51
       COLLATIONPROPERTY(N'Latin1_General_100_CI_AS',     'SortID'); --  0

La única diferencia entre las dos primeras colaciones es la sensibilidad a mayúsculas y minúsculas. La tercera intercalación es una intercalación de Windows y, por lo tanto, no tiene una tabla de asignación estática.

Además, estas clasificaciones deben clasificarse y compararse más rápido que las clasificaciones de Windows debido a que son simples búsquedas de caracteres para clasificar el peso. Sin embargo, estas intercalaciones también son mucho menos funcionales y generalmente deben evitarse si es posible.

Ventanas

Las intercalaciones de Windows (aquellas con nombres que no comienzan con SQL_) son la forma más nueva de ordenar / comparar (comenzando en SQL Server 2000). En este modelo Unicode más nuevo y complejo, cada combinación de configuración regional, página de códigos y las diversas sensibilidades no reciben una asignación estática. Por un lado, no hay páginas de códigos en este modelo. Este modelo asigna un valor de clasificación predeterminado a cada carácter, y luego cada localidad / cultura puede reasignar los valores de clasificación a cualquier número de caracteres. Esto permite que múltiples culturas usen los mismos personajes de diferentes maneras. Esto tiene el efecto de permitir que varios idiomas se ordenen naturalmente usando la misma clasificación si no usan los mismos caracteres (y si uno de ellos no necesita reasignar ningún valor y simplemente puede usar los valores predeterminados).

Los valores de clasificación en este modelo no son valores únicos. Son una matriz de valores que asignan pesos relativos a la letra base, cualquier signo diacrítico (es decir, acentos), mayúsculas y minúsculas, etc. Si la intercalación distingue entre mayúsculas y minúsculas, se utiliza la parte de "mayúsculas" de esa matriz, de lo contrario se ignora ( por lo tanto, insensible). Si la intercalación es sensible al acento, se usa la porción "diacrítica" de la matriz, de lo contrario se ignora (por lo tanto, insensible).

Las comparaciones en este modelo son una operación de varios pasos:

  1. Primero, la cadena se normaliza de modo que se igualen varias formas de representar el mismo carácter. Por ejemplo, " ü " podría ser un solo carácter / punto de código (U + 00FC). También puede combinar una " u " sin acento (U + 0075) con una Diaéresis combinada " ̈ " (U + 0308) para obtener: " ü ", que no solo se ve igual cuando se procesa (a menos que haya un problema con su fuente), pero también se considera que es la misma que la versión de un solo carácter (U + 00FC), a menos que utilice una intercalación binaria (que compara bytes en lugar de caracteres). La normalización divide el carácter individual en varias piezas, que incluyen expansiones para caracteres como "  Æ  " (como se indicó anteriormente para las intercalaciones de SQL Server).
  2. La operación de comparación en este modelo va carácter por carácter por cada sensibilidad . Las claves de clasificación para las cadenas se determinan aplicando los elementos apropiados de cada conjunto de valores de clasificación de caracteres en función de qué sensibilidades son "sensibles". Los valores de la clave de clasificación están ordenados por todas las sensibilidades primarias de cada carácter (el carácter base), seguidas por todas las sensibilidades secundarias (peso diacrítico), seguidas por el peso de mayúsculas y minúsculas de cada carácter, y así sucesivamente.
  3. La ordenación se realiza en función de las claves de ordenación calculadas. Con cada sensibilidad agrupada, puede obtener un orden de clasificación diferente del que obtendría con una intercalación de SQL Server equivalente al comparar cadenas de varios caracteres, y los acentos están involucrados, y la intercalación es sensible al acento (y aún más si la intercalación es también distingue entre mayúsculas y minúsculas).

Para obtener más detalles sobre esta clasificación, eventualmente publicaré una publicación que muestre los valores de clave de clasificación, cómo se calculan, las diferencias entre SQL Server y las intercalaciones de Windows, etc. Pero por ahora, vea mi respuesta a: Clasificación sensible acentuada ( tenga en cuenta que la otra respuesta a esa pregunta es una buena explicación del algoritmo oficial Unicode, pero SQL Server utiliza un algoritmo personalizado, aunque similar, e incluso una tabla de peso personalizada).

Todas las sensibilidades se pueden ajustar en estas intercalaciones: "mayúsculas", "acento", "ancho", "tipo kana" y "selector de variación" (a partir de SQL Server 2017, y solo para las intercalaciones japonesas). Además, algunas de estas intercalaciones (cuando se usan con datos Unicode) admiten caracteres suplementarios (a partir de SQL Server 2012). Este enfoque se aplica tanto a los datos NVARCHAR como a los VARCHAR datos (incluso los datos que no son Unicode). Se aplica a VARCHARdatos que no son Unicode convirtiendo primero el valor a Unicode internamente y luego aplicando las reglas de clasificación / comparación.


Tenga en cuenta:

  1. No existe una clasificación universal predeterminada para SQL Server. Hay un valor predeterminado de instalación que difiere según la configuración regional / de idioma actual del sistema operativo en el momento de la instalación (que desafortunadamente es SQL_Latin1_General_CP1_CI_ASpara los sistemas de inglés de EE. UU., Por lo tanto , vote por esta sugerencia ). Esto se puede cambiar durante la instalación. Esta clasificación a nivel de instancia establece la clasificación para la base de [model]datos, que es la plantilla utilizada al crear nuevas bases de datos, pero la clasificación se puede cambiar al ejecutar CREATE DATABASEespecificando la COLLATEcláusula. Esta clasificación a nivel de base de datos se usa para literales variables y de cadena, así como el valor predeterminado para columnas nuevas (¡y alteradas!) Cuando COLLATEno se especifica la cláusula (que es el caso del código de ejemplo en la pregunta).
  2. Para obtener más información sobre intercalaciones / codificaciones / Unicode, visite: Información de intercalaciones
Solomon Rutzky
fuente
5

Por lo general, esto se implementa utilizando tablas de clasificación que asignan una determinada puntuación a cada personaje. La rutina de clasificación tiene un comparador que usa una tabla apropiada, ya sea predeterminada o especificada explícitamente, para comparar cadenas, carácter por carácter, usando sus puntuaciones de clasificación. Si, por ejemplo, una tabla de clasificación particular asigna un puntaje de 1 a "a" y 201 a "A", y un puntaje más bajo en esta implementación particular significa mayor prioridad, entonces "a" se ordenará antes de "A". Otra tabla podría asignar puntuaciones inversas: 201 a "a" y 1 a "A", y el orden de clasificación será posteriormente inverso. Sin embargo, otra tabla podría asignar puntajes iguales a "a", "A", "Á" y "Å", lo que conduciría a una comparación y clasificación insensible a mayúsculas y minúsculas.

De manera similar, dicho comparador basado en tablas de colación se usa al comparar una clave de índice con el valor proporcionado en el predicado.

mustaccio
fuente
1
Solo para su información: esta información solo es correcta en términos de uso de intercalaciones de SQL Server (es decir, aquellas con nombres que comienzan con SQL_) cuando se usa en VARCHARdatos. Esto no es exactamente cierto para los NVARCHARdatos o VARCHARdatos cuando se utiliza una intercalación de Windows (los nombres no comienzan con SQL_).
Solomon Rutzky