이 쿼리에 따라 서버의 기본 데이터 정렬은 Latin1_General_CI_AS입니다.
SELECT SERVERPROPERTY('Collation') AS Collation;
이 데이터 정렬을 사용하면 술어를 사용하여 문자열의 숫자가 아닌 문자를 일치시킬 수 있다는 사실에 놀랐습니다 LIKE '[0-9]'
.
기본 데이터 정렬에서 왜 이런 일이 발생합니까? 이것이 유용한 경우를 생각할 수 없습니다. 이진 데이터 정렬을 사용하여 문제를 해결할 수 있지만 기본 데이터 정렬을 구현하는 이상한 방법처럼 보입니다.
숫자를 필터링하면 숫자가 아닌 카락 터가 생성됩니다.
가능한 모든 1 바이트 문자 값을 포함하는 열을 작성하고 숫자 일치 술어로 값을 필터링하여 동작을 시연 할 수 있습니다.
다음 명령문은 현재 코드 페이지의 각 코드 포인트마다 하나씩 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 ÿ
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