Die Standardkollatierung meines Servers ist Latin1_General_CI_AS, wie durch diese Abfrage bestimmt:
SELECT SERVERPROPERTY('Collation') AS Collation;
Es hat mich überrascht, dass ich mit dieser Kollatierung Zeichen in Zeichenfolgen, die keine Ziffern sind, anhand des Prädikats abgleichen kann LIKE '[0-9]'
.
Warum geschieht dies in der Standardsortierung? Ich kann mir keinen Fall vorstellen, in dem dies nützlich wäre. Ich weiß, dass ich das Verhalten mit einer binären Kollatierung umgehen kann, aber es scheint eine seltsame Art zu sein, die Standardkollatierung zu implementieren.
Durch das Filtern von Ziffern werden nicht-stellige Zeichen erzeugt
Ich kann das Verhalten veranschaulichen, indem ich eine Spalte erstelle, die alle möglichen Einzelbytezeichenwerte enthält, und die Werte mit dem Prädikat für die Ziffernübereinstimmung filtere.
Die folgende Anweisung erstellt eine temporäre Tabelle mit 256 Zeilen, eine für jeden Codepunkt in der aktuellen Codepage:
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;
Jede Zeile enthält den ganzzahligen Wert des Codepunkts und den Zeichenwert des Codepunkts. Nicht alle Zeichenwerte können angezeigt werden. Einige der Codepunkte sind ausschließlich Kontrollzeichen. Hier ist eine Auswahl der Ausgabe von 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 ÿ
Ich würde erwarten, in der Lage zu sein, in der Symbolspalte nach Ziffern zu filtern, indem ich ein LIKE-Prädikat verwende und den Bereich der Zeichen '0' bis '9' spezifiziere:
SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0-9]';
Es erzeugt eine überraschende Ausgabe:
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 ¾
Die Codepunkte 48 bis 57 sind die, die ich erwarte. Was mich überrascht, ist, dass die Symbole für Hoch- und Nachkommastellen auch in der Ergebnismenge enthalten sind!
Es mag einen mathematischen Grund geben, Exponenten und Brüche als Zahlen zu betrachten, aber es scheint falsch, sie Ziffern zu nennen.
Verwenden der binären Kollatierung als Problemumgehung
Ich verstehe, dass ich die entsprechende binäre Kollatierung Latin1_General_BIN erzwingen kann, um das erwartete Ergebnis zu erhalten:
SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0-9]' COLLATE Latin1_General_BIN;
Die Ergebnismenge enthält nur die Codepunkte 48 bis 57:
CodePoint Symbol
48 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9