Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Qual é o objetivo de COLLATIONS para colunas nvarchar (Unicode)?


Armazenar e representar caracteres é uma coisa, e saber classificá-los e compará-los é outra.

Dados Unicode, armazenados no XML e N -tipos prefixados no SQL Server, podem representar todos os caracteres em todos os idiomas (na maioria das vezes, e esse é o objetivo) com um único conjunto de caracteres. Então, para NCHAR / NVARCHAR data (estou deixando de fora NTEXT já que não deve mais ser usado, e XML como não é afetado por Collations), os Collations não alteram quais caracteres podem ser armazenados. Para CHAR e VARCHAR dados, os agrupamentos fazem afetam o que pode ser armazenado, pois cada agrupamento aponta para uma página de código específica, que determina o que pode ser armazenado nos valores 128 - 255.

Agora, embora haja uma ordem de classificação padrão para todos os caracteres, isso não pode funcionar em todos os idiomas e culturas. Existem muitos idiomas que compartilham alguns / muitos / todos os caracteres, mas possuem regras diferentes para classificá-los. Por exemplo, a letra "C" vem antes da letra "D" na maioria dos alfabetos que usam essas letras. Em inglês dos EUA, uma combinação de "C" e "H" (ou seja, "CH" como duas letras separadas) viria naturalmente antes de qualquer string começando com um "D". Mas, em alguns idiomas, a combinação de duas letras de "CH" é especial e classifica depois "D":
IF (   N'CH' COLLATE Czech_CI_AI > N'D' COLLATE Czech_CI_AI
   AND N'C'  COLLATE Czech_CI_AI < N'D' COLLATE Czech_CI_AI
   AND N'CI' COLLATE Czech_CI_AI < N'D' COLLATE Czech_CI_AI
   ) PRINT 'Czech_CI_AI';

IF (   N'CH' COLLATE Czech_100_CI_AI > N'D' COLLATE Czech_100_CI_AI
   AND N'C'  COLLATE Czech_100_CI_AI < N'D' COLLATE Czech_100_CI_AI
   AND N'CI' COLLATE Czech_100_CI_AI < N'D' COLLATE Czech_100_CI_AI
   ) PRINT 'Czech_100_CI_AI';

IF (   N'CH' COLLATE Slovak_CI_AI > N'D' COLLATE Slovak_CI_AI
   AND N'C'  COLLATE Slovak_CI_AI < N'D' COLLATE Slovak_CI_AI
   AND N'CI' COLLATE Slovak_CI_AI < N'D' COLLATE Slovak_CI_AI
   ) PRINT 'Slovak_CI_AI';

IF (   N'CH' COLLATE Slovak_CS_AS > N'D' COLLATE Slovak_CS_AS
   AND N'C'  COLLATE Slovak_CS_AS < N'D' COLLATE Slovak_CS_AS
   AND N'CI' COLLATE Slovak_CS_AS < N'D' COLLATE Slovak_CS_AS
   ) PRINT 'Slovak_CS_AS';

IF (   N'CH' COLLATE Latin1_General_100_CI_AS > N'D' COLLATE Latin1_General_100_CI_AS
   AND N'C'  COLLATE Latin1_General_100_CI_AS < N'D' COLLATE Latin1_General_100_CI_AS
   AND N'CI' COLLATE Latin1_General_100_CI_AS < N'D' COLLATE Latin1_General_100_CI_AS
   ) PRINT 'Latin1_General_100_CI_AS'
ELSE PRINT 'Nope!';

Devoluções:
Czech_CI_AI
Czech_100_CI_AI
Slovak_CI_AI
Slovak_CS_AS
Nope!

Para ver exemplos de regras de classificação em várias culturas, consulte:Gráficos de agrupamento .

Além disso, em alguns idiomas, certas letras ou combinações de letras equivalem a outras letras de uma maneira que não ocorre na maioria dos outros idiomas. Por exemplo, apenas em dinamarquês um "å" equivale a "aa". Mas, o "å" não equivale a apenas um único "a":
IF (N'aa' COLLATE Danish_Greenlandic_100_CI_AI =  N'å' COLLATE Danish_Greenlandic_100_CI_AI
AND N'a'  COLLATE Danish_Greenlandic_100_CI_AI <> N'å' COLLATE Danish_Greenlandic_100_CI_AI
   ) PRINT 'Danish_Greenlandic_100_CI_AI';

IF (   N'aa' COLLATE Danish_Norwegian_CI_AI =  N'å' COLLATE Danish_Norwegian_CI_AI
   AND N'a'  COLLATE Danish_Norwegian_CI_AI <> N'å' COLLATE Danish_Norwegian_CI_AI
   ) PRINT 'Danish_Norwegian_CI_AI';

IF (   N'aa' COLLATE Latin1_General_100_CI_AI =  N'å' COLLATE Latin1_General_100_CI_AI
   AND N'a'  COLLATE Latin1_General_100_CI_AI <> N'å' COLLATE Latin1_General_100_CI_AI
   ) PRINT 'Latin1_General_100_CI_AI'
ELSE PRINT 'Nope!';

Devoluções:
Danish_Greenlandic_100_CI_AI
Danish_Norwegian_CI_AI
Nope!

Isso tudo é altamente complexo, e eu nem mencionei o manuseio de idiomas da direita para a esquerda (hebraico e árabe), chinês, japonês, combinação de caracteres etc.

Se você quiser uma visão aprofundada das regras, confira o Unicode Collation Algorithm (UCA) . Os exemplos acima são baseados em exemplos dessa documentação, embora eu não acredite que todas as regras do UCA tenham sido implementadas, especialmente porque os agrupamentos do Windows (os agrupamentos não começando com SQL_ ) são baseados em Unicode 5.0 ou 6.0, dependendo do sistema operacional que você está usando e da versão do .NET Framework instalada (consulte SortVersion para detalhes).

Então é isso que os Collations fazem. Se você quiser ver todos os agrupamentos disponíveis, basta executar o seguinte:
SELECT [name] FROM sys.fn_helpcollations() ORDER BY [name];