Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Quel est l'intérêt de COLLATIONS pour les colonnes nvarchar (Unicode) ?

Stocker et représenter des caractères est une chose, savoir les trier et les comparer en est une autre.

Données Unicode, stockées dans le XML et N -les types préfixés dans SQL Server, peuvent représenter tous les caractères dans toutes les langues (pour la plupart, et c'est son objectif) avec un seul jeu de caractères. Donc pour NCHAR / NVARCHAR données (j'omets NTEXT car il ne devrait plus être utilisé, et XML car il n'est pas affecté par les classements), les classements ne changent pas les caractères pouvant être stockés. Pour CHAR et VARCHAR données, les Collations font affectent ce qui peut être stocké car chaque classement pointe vers une page de code particulière, qui détermine ce qui peut être stocké dans les valeurs 128 à 255.

Maintenant, bien qu'il existe un ordre de tri par défaut pour tous les caractères, cela ne peut pas fonctionner dans toutes les langues et cultures. Il existe de nombreuses langues qui partagent certains / plusieurs / tous les caractères, mais ont des règles différentes pour les trier. Par exemple, la lettre "C" vient avant la lettre "D" dans la plupart des alphabets qui utilisent ces lettres. En anglais américain, une combinaison de "C" et "H" (c'est-à-dire "CH" en deux lettres distinctes) viendrait naturellement avant toute chaîne commençant par un "D". Mais, dans quelques langues, la combinaison à deux lettres de "CH" est spéciale et trie après "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!';

Renvoie :

Czech_CI_AI
Czech_100_CI_AI
Slovak_CI_AI
Slovak_CS_AS
Nope!

Pour voir des exemples de règles de tri dans différentes cultures, veuillez consulter :Tableaux de classement .

De plus, dans certaines langues, certaines lettres ou combinaisons de lettres correspondent à d'autres lettres d'une manière qu'elles ne font pas dans la plupart des autres langues. Par exemple, ce n'est qu'en danois qu'un "å" équivaut à "aa". Mais, le "å" n'équivaut pas à un seul "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!';

Renvoie :

Danish_Greenlandic_100_CI_AI
Danish_Norwegian_CI_AI
Nope!

Tout cela est très complexe, et je n'ai même pas mentionné la gestion des langues qui s'écrivent de droite à gauche (hébreu et arabe), le chinois, le japonais, les combinaisons de caractères, etc.

Si vous souhaitez avoir un aperçu approfondi des règles, consultez Unicode Collation Algorithm (UCA) . Les exemples ci-dessus sont basés sur des exemples de cette documentation, bien que je ne pense pas que toutes les règles de l'UCA aient été implémentées, en particulier depuis les classements Windows (collations pas commençant par SQL_ ) sont basés sur Unicode 5.0 ou 6.0, selon le système d'exploitation que vous utilisez et la version de .NET Framework installée (voir SortVersion pour plus de détails).

C'est donc ce que font les Collations. Si vous souhaitez voir tous les classements disponibles, exécutez simplement ce qui suit :

SELECT [name] FROM sys.fn_helpcollations() ORDER BY [name];