Le type de classement par défaut dans SQL Server permet l'indexation par rapport aux chaînes insensibles à la casse, mais la casse des données est persistante. Comment cela fonctionne-t-il réellement? Je cherche les vrais écrous et boulons, bits et octets, ou une bonne ressource qui l'explique en détail.
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'
Questions sur les classements SQL Server que vous étiez trop timides à poser par Robert Sheldon explique comment utiliser le classement. Il ne couvre pas le fonctionnement du classement. Je suis intéressé par la façon dont un index peut être créé/interrogé efficacement sans se soucier du cas, tout en stockant simultanément les données du cas.
indexation par rapport aux chaînes insensibles à la casse, mais le cas des données est conservé. Comment cela fonctionne-t-il réellement?
Ce n'est en fait pas un comportement spécifique à SQL Server, c'est juste comment ces choses fonctionnent en général.
Ainsi, les données sont les données. Si vous parlez d'un index en particulier, les données ont besoin pour être stockées car autrement, cela nécessiterait une recherche dans la table principale à chaque fois pour obtenir la valeur réelle, et il y aurait aucune possibilité d'index de couverture (du moins pas pour les types de chaîne).
Les données, dans la table/l'index clusterisé ou l'index non clusterisé, contiennent pas contient des informations de classement/tri. Ce sont simplement des données. Le classement (règles locales/culturelles et sensibilités) n'est que des métadonnées attachées à la colonne et utilisées lorsqu'une opération de tri est appelée (sauf si remplacée par une clause COLLATE
), qui comprendrait la création/reconstruction d'un index . Les règles définies par un classement non binaire sont utilisées pour générer des clés de tri, qui sont des représentations binaires de la chaîne (les clés de tri ne sont pas nécessaires dans les classements binaires). Ces représentations binaires incorporent toutes les règles locales/culturelles et les sensibilités sélectionnées. Les clés de tri sont utilisées pour placer les enregistrements dans leur ordre correct, mais elles ne sont pas elles-mêmes stockées dans l'index ou la table. Ils ne sont pas stockés (au moins je n'ai pas vu ces valeurs dans l'index et on m'a dit qu'ils ne sont pas stockés) parce que:
Il existe deux types de classements: SQL Server et Windows.
Classements SQL Server (ceux dont le nom commence par SQL_
) est la méthode de tri/comparaison antérieure à SQL Server 2000 (même si SQL_Latin1_General_CP1_CI_AS
est toujours la valeur par défaut de l'installation sur les systèmes d'exploitation en anglais américain, malheureusement). Dans ce modèle ancien, simpliste et non Unicode, chaque combinaison de paramètres régionaux, de page de codes et des différentes sensibilités reçoit un mappage statique de chacun des caractères de cette page de codes. Chaque caractère se voit attribuer une valeur (c'est-à-dire un poids de tri) pour indiquer comment il correspond aux autres. Les comparaisons dans ce modèle semblent faire une opération en deux passes:
Les seules sensibilités pouvant être ajustées dans ces classements sont: "case" et "accent" ("width", "kana type" et "variation selector" ne sont pas disponibles). De plus, aucun de ces classements ne prend en charge les caractères supplémentaires (ce qui est logique car ils sont spécifiques à Unicode et ces classements ne s'appliquent qu'aux données non Unicode).
Cette approche s'applique uniquement aux données non Unicode VARCHAR
. Chaque combinaison unique de paramètres régionaux, de code la page, la casse et la sensibilité aux accents ont un "ID de tri" spécifique, que vous pouvez voir dans l'exemple suivant:
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 seule différence entre les deux premiers classements est la sensibilité à la casse. Le troisième classement est un classement Windows et n'a donc pas de table de mappage statique.
En outre, ces classements doivent trier et comparer plus rapidement que les classements Windows en raison de la simple recherche de caractères pour trier le poids. Cependant, ces classements sont également beaucoup moins fonctionnels et devraient généralement être évités si possible.
Classements Windows (ceux avec des noms pas commençant par SQL_
) est la nouvelle méthode de tri/comparaison (à partir de SQL Server 2000). Dans ce modèle Unicode plus récent et complexe, chaque combinaison de paramètres régionaux, de page de codes et des différentes sensibilités est pas avec un mappage statique. D'une part, il n'y a pas de pages de codes dans ce modèle. Ce modèle attribue une valeur de tri par défaut à chaque caractère, puis chaque environnement local/culture peut réaffecter des valeurs de tri à n'importe quel nombre de caractères. Cela permet à plusieurs cultures d'utiliser les mêmes personnages de différentes manières. Cela a pour effet de permettre que plusieurs langues soient triées naturellement en utilisant le même classement si elles n'utilisent pas les mêmes caractères (et si l'une d'entre elles n'a pas besoin de réaffecter de valeurs et peut simplement utiliser les valeurs par défaut).
Les valeurs de tri dans ce modèle ne sont pas des valeurs uniques. Il s'agit d'un tableau de valeurs qui attribuent des poids relatifs à la lettre de base, à tous les signes diacritiques (c'est-à-dire les accents), à la casse, etc. Si le classement est sensible à la casse, la partie "casse" de ce tableau est utilisée, sinon il est ignoré ( donc insensible). Si le classement est sensible à l'accent, alors la partie "diacritique" du tableau est utilisée, sinon il est ignoré (donc insensible).
Les comparaisons dans ce modèle sont une opération à plusieurs passes:
Pour plus de détails sur ce tri, je publierai éventuellement un article qui montre les valeurs des clés de tri, comment elles sont calculées, les différences entre les classements SQL Server et Windows, etc. Mais pour l'instant, veuillez voir ma réponse à: Accent Sensitive Sort (veuillez noter que l'autre réponse à cette question est une bonne explication de l'algorithme Unicode officiel, mais SQL Server utilise à la place un algorithme personnalisé, bien que similaire, et même une table de pondération personnalisée).
Toutes les sensibilités peuvent être ajustées dans ces classements: "case", "accent", "width", "kana type" et "variation selector" (à partir de SQL Server 2017, et uniquement pour les classements japonais). En outre, certains de ces classements (lorsqu'ils sont utilisés avec des données Unicode) prennent en charge les caractères supplémentaires (à partir de SQL Server 2012). Cette approche s'applique aux données NVARCHAR
etVARCHAR
(même les données non Unicode). Il s'applique aux données non-Unicode VARCHAR
en convertissant d'abord la valeur en Unicode en interne, puis en appliquant les règles de tri/comparaison.
Notez s'il vous plaît:
SQL_Latin1_General_CP1_CI_AS
pour les systèmes en anglais américain, donc veuillez voter pour cette suggestion ). Cela peut être modifié pendant l'installation. Ce classement au niveau de l'instance définit ensuite le classement pour le [model]
DB qui est le modèle utilisé lors de la création de nouvelles bases de données, mais le classement peut être modifié lors de l'exécution de CREATE DATABASE
en spécifiant la clause COLLATE
. Ce classement au niveau de la base de données est utilisé pour les littéraux de variable et de chaîne, ainsi que par défaut pour les nouvelles colonnes (et modifiées!) Lorsque la clause COLLATE
n'est pas spécifiée (ce qui est le cas pour l'exemple de code dans la question ).En règle générale, cela est mis en œuvre à l'aide de tables de classement qui attribuent un certain score à chaque personnage. La routine de tri a un comparateur qui utilise une table appropriée, par défaut ou spécifiée explicitement, pour comparer les chaînes, caractère par caractère, en utilisant leurs scores de classement. Si, par exemple, une table de classement particulière attribue un score de 1 à "a" et de 201 à "A", et un score inférieur dans cette implémentation particulière signifie une priorité plus élevée, alors "a" sera trieur avant "A". Un autre tableau peut attribuer des scores inversés: 201 à "a" et 1 à "A", et l'ordre de tri sera ensuite inversé. Encore un autre tableau pourrait attribuer des scores égaux à "a", "A", "Á" et "Å", ce qui conduirait à une comparaison et un tri insensibles à la casse et à l'accent.
De même, un tel comparateur basé sur une table de classement est utilisé lors de la comparaison d'une clé d'index avec la valeur fournie dans le prédicat.