Le classement par défaut de mon serveur est Latin1_General_CI_AS, comme déterminé par cette requête:
SELECT SERVERPROPERTY('Collation') AS Collation;
J'ai été surpris de découvrir qu'avec ce classement, je peux faire correspondre des caractères non numériques dans des chaînes en utilisant le prédicat LIKE '[0-9]'
.
Pourquoi dans le classement par défaut cela se produit-il? Je ne peux pas penser à un cas où cela serait utile. Je sais que je peux contourner le problème en utilisant un classement binaire, mais cela semble être une façon étrange d'implémenter le classement par défaut.
Le filtrage des chiffres produit des caractères non numériques
Je peux démontrer le comportement en créant une colonne qui contient toutes les valeurs de caractères possibles sur un octet et en filtrant les valeurs avec le prédicat de correspondance de chiffres.
L'instruction suivante crée une table temporaire avec 256 lignes, une pour chaque point de code dans la page de codes actuelle:
WITH P0(_) AS (SELECT 0 UNION ALL SELECT 0),
P1(_) AS (SELECT 0 FROM P0 AS L CROSS JOIN P0 AS R),
P2(_) AS (SELECT 0 FROM P1 AS L CROSS JOIN P1 AS R),
P3(_) AS (SELECT 0 FROM P2 AS L CROSS JOIN P2 AS R),
Tally(Number) AS (
SELECT -1 + ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM P3
)
SELECT Number AS CodePoint, CHAR(Number) AS Symbol
INTO #CodePage
FROM Tally
WHERE Number >= 0 AND Number <= 255;
Chaque ligne contient la valeur entière du point de code et la valeur de caractère du point de code. Toutes les valeurs de caractères ne peuvent pas être affichées - certains des points de code sont strictement des caractères de contrôle. Voici un échantillon sélectif de la sortie de SELECT CodePoint, Symbol FROM #CodePage
:
0
1
2
...
32
33 !
34 "
35 #
...
48 0
49 1
50 2
...
65 A
66 B
67 C
...
253 ý
254 þ
255 ÿ
Je m'attendrais à pouvoir filtrer sur la colonne Symbole pour trouver des caractères numériques en utilisant un prédicat LIKE et en spécifiant la plage de caractères de '0' à '9':
SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0-9]';
Il produit une sortie surprenante:
CodePoint Symbol
48 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9
178 ²
179 ³
185 ¹
188 ¼
189 ½
190 ¾
L'ensemble des points de code 48 à 57 sont ceux que j'attends. Ce qui me surprend, c'est que les symboles pour les exposants et les fractions sont également inclus dans le jeu de résultats!
Il peut y avoir une raison mathématique de considérer les exposants et les fractions comme des nombres, mais il semble incorrect de les appeler des chiffres.
Utilisation du classement binaire comme solution de contournement
Je comprends que pour obtenir le résultat attendu, je peux forcer le classement binaire correspondant Latin1_General_BIN:
SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0-9]' COLLATE Latin1_General_BIN;
L'ensemble de résultats comprend uniquement les points de code 48 à 57:
CodePoint Symbol
48 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9
la source