Параметр мого сервера за замовчуванням - Latin1_General_CI_AS, як визначено цим запитом:
SELECT SERVERPROPERTY('Collation') AS Collation;
Я з подивом виявив, що за допомогою цього зіставлення я можу зіставити нецифрові символи в рядках за допомогою присудка LIKE '[0-9]'
.
Чому в порівнянні за замовчуванням це відбувається? Я не можу придумати випадок, коли це було б корисно. Я знаю, що я можу обійти поведінку, використовуючи двійкове порівняння, але це здається дивним способом реалізації зіставлення за замовчуванням.
Фільтр цифр дає нецифрові символи
Я можу продемонструвати поведінку, створивши стовпець, який містить усі можливі однобайтові значення символів та фільтруючи значення за допомогою предиката відповідності цифр.
Наступне твердження створює тимчасову таблицю з 256 рядками, по одному для кожної точки коду на поточній кодовій сторінці:
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;
Кожен рядок містить ціле значення кодової точки та значення символу кодової точки. Не всі значення символів відображаються - деякі кодові точки є строго керованими символами. Ось вибіркова вибірка виходу 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 ÿ
Я б очікував, що зможе фільтрувати стовпчик Symbol, щоб знайти знакові символи за допомогою предиката LIKE та вказати діапазон символів '0' до '9':
SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0-9]';
Це дає дивовижний вихід:
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 ¾
Набір кодових точок 48 до 57 - це те, що я очікую. Що мене дивує, це те, що символи для суперскриптів та дробів також включені до набору результатів!
Може бути математична причина вважати експоненти і дроби як числа, але здається неправильним називати їх цифрами.
Використання двійкового порівняння як вирішення
Я розумію, що для отримання очікуваного результату я можу змусити відповідне бінарне порівняння Latin1_General_BIN:
SELECT CodePoint, Symbol
FROM #CodePage
WHERE Symbol LIKE '[0-9]' COLLATE Latin1_General_BIN;
Набір результатів включає лише кодові точки 48 до 57:
CodePoint Symbol
48 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9