악센트 구분


19

왜이 두 SELECT문장이 다른 정렬 순서를 가지나요?

USE tempdb;
CREATE TABLE dbo.OddSort 
(
    id INT IDENTITY(1,1) PRIMARY KEY
    , col1 NVARCHAR(2)
    , col2 NVARCHAR(2)
);
GO
INSERT dbo.OddSort (col1, col2) 
VALUES (N'e', N'eA')
    , (N'é', N'éB')
    , (N'ë', N'ëC')
    , (N'è', N'èD')
    , (N'ê', N'êE')
    , (N'ē', N'ēF');
GO

SELECT * 
FROM dbo.OddSort 
ORDER BY col1 COLLATE Latin1_General_100_CS_AS;
╔ ==== ╦ ====== ╦ ====== ╗
║ id ║ col1 ║ col2 ║
╠ ==== ╬ ====== ╬ ====== ╣
║ 1 ║ e ║ eA ║
║ 2 ║ é ║ éB ║
║ 4 ║ è ║ èD ║-id 3이어야합니까?
║ 5 ║ ê ║ êE ║
║ 3 ║ ë ║ ëC ║
║ 6 ║ ē ║ ēF ║
╚ ==== ╩ ====== ╩ ====== ╝
SELECT * 
FROM dbo.OddSort 
ORDER BY col2 COLLATE Latin1_General_100_CS_AS;
╔ ==== ╦ ====== ╦ ====== ╗
║ id ║ col1 ║ col2 ║
╠ ==== ╬ ====== ╬ ====== ╣
║ 1 ║ e ║ eA ║
║ 2 ║ é ║ éB ║
║ 3 ║ ë ║ ëC ║
║ 4 ║ è ║ èD ║
║ 5 ║ ê ║ êE ║
║ 6 ║ ē ║ ēF ║
╚ ==== ╩ ====== ╩ ====== ╝

답변:


13

이 질문은 데이터베이스와 관련이 없지만 유니 코드 처리 및 규칙에 관한 것입니다.

를 기반으로 https://docs.microsoft.com/en-us/sql/t-sql/statements/windows-collation-name-transact-sql Latin1_General_100_CS_AS 방법 : "데이터 정렬 코드 페이지에 대한 규칙과지도를 정렬 라틴어 일반 사전을 사용 CS = 대소 문자 구분 및 AS = 악센트 구분이 추가 된 1252 "

Windows 코드 페이지 1252와 유니 코드 ( http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT ) 간의 매핑 은 처리중인 모든 문자에 대해 동일한 값을 표시합니다 (매크로를 제외하고는 제외) Microsoft 매핑에는 존재하지 않으므로이 경우 어떻게되는지 알지 못하므로 지금은 유니 코드 도구 및 용어에 집중할 수 있습니다.

먼저 모든 문자열에 대해 우리가 다루고있는 것을 정확하게 알려주십시오.

0065  LATIN SMALL LETTER E
0041  LATIN CAPITAL LETTER A
00E9  LATIN SMALL LETTER E WITH ACUTE
0042  LATIN CAPITAL LETTER B
00EB  LATIN SMALL LETTER E WITH DIAERESIS
0043  LATIN CAPITAL LETTER C
00E8  LATIN SMALL LETTER E WITH GRAVE
0044  LATIN CAPITAL LETTER D
00EA  LATIN SMALL LETTER E WITH CIRCUMFLEX
0045  LATIN CAPITAL LETTER E
0113  LATIN SMALL LETTER E WITH MACRON
0046  LATIN CAPITAL LETTER F

유니 코드 데이터 정렬 알고리즘은 https://www.unicode.org/reports/tr10/에 설명되어 있습니다.

일부 규칙은 상황에 따라 다르기 때문에 정렬이 한 문자에만 의존 할 수 없음을 설명하는 1.3 "문맥 민감도"섹션을 살펴보십시오.

1.8의 다음 사항도 참고하십시오.

데이터 정렬은 문자열의 속성이 아닙니다. 데이터 정렬 순서는 일반적으로 연결 또는 하위 문자열 작업에서 유지되지 않습니다.

기본적으로이 알고리즘은 완전히 사용자 정의 가능한 세 가지 수준을 사용합니다. 라틴어 스크립트의 경우이 수준은 대략 다음과 같습니다.

alphabetic ordering
diacritic ordering
case ordering.

그러나 알고리즘 자체는 약간 조밀합니다. 그 요지는 다음 바와 짧게 유니 코드 문자 정렬 알고리즘을위한지도 데이터를 포함하는 입력의 유니 코드 문자열 대조 요소 테이블을 걸린다. 부호없는 16 비트 정수의 배열 인 정렬 키를 생성합니다. 이렇게 생성 된 둘 이상의 정렬 키는 이진 비교되어 생성 된 문자열을 정확하게 비교할 수 있습니다.

특정 라틴어 정렬 규칙은 여기 ( http://developer.mimer.com/collations/charts/latin.htm) 이상 에서 볼 수 있습니다 . 0409.1252.Latin1_General_CS_AS.html

를 들어 e캐릭터 그것을 보여줍니다 :

e E É è È ê Ê ë Ë

이것은 col1코드 페이지 1252에 ē가 존재하지 않는다는 점을 제외하고 주문할 때의 결과를 설명 하므로 그 기능에 대한 아이디어는 전혀 없습니다.

또는 직접 유니 코드 알고리즘을 수행하는 경우 http://www.unicode.org/Public/UCA/latest/allkeys.txt 에서 DUCET의 키 값을 사용 하십시오 .

1 단계 : 정규화 양식 D이므로 각 경우는 다음과 같습니다.

e => U+0065
é => U+0065 U+0301
ë => U+0065 U+0308
è => U+0065 U+0300
ê => U+0065 U+0302
ē => U+0065 U+0304

2 단계, 데이터 정렬 배열 생성 (파일에서 조회 allkeys.txt)

e => [.1D10.0020.0002]
é => [.1D10.0020.0002] [.0000.0024.0002]
ë => [.1D10.0020.0002] [.0000.002B.0002]
è => [.1D10.0020.0002] [.0000.0025.0002]
ê => [.1D10.0020.0002] [.0000.0027.0002]
ē => [.1D10.0020.0002] [.0000.0032.0002]

3 단계, 양식 정렬 키 (각 레벨에 대해 각 조합 배열 내에서 각 값을 가져 와서 0000을 분리 문자로두고 다음 레벨에서 다시 시작)

e => 1D10 0000 0020 0000 0002
é => 1D10 0000 0020 0024 0000 0002 0002
ë => 1D10 0000 0020 002B 0000 0002 0002
è => 1D10 0000 0020 0025 0000 0002 0002
ê => 1D10 0000 0020 0027 0000 0002 0002
ē => 1D10 0000 0020 0032 0000 0002 0002

4 단계, 정렬 키 비교 (각 값을 하나씩 간단하게 이진 비교) : 네 번째 값은 모두 정렬하기에 충분하므로 최종 순서는 다음과 같습니다.

e
é
è
ê
ë
ē

주문과 같은 방법으로 col2:

1 단계 : NFD

eA => U+0065 U+0041
éB => U+0065 U+0301 U+0042
ëC => U+0065 U+0308 U+0043
èD => U+0065 U+0300 U+0044
êE => U+0065 U+0302 U+0045
ēF => U+0065 U+0304 U+0046

2 단계 : 콜 레이션 배열

eA => [.1D10.0020.0002] [.1CAD.0020.0008]
éB => [.1D10.0020.0002] [.0000.0024.0002] [.1CC6.0020.0008]
ëC => [.1D10.0020.0002] [.0000.002B.0002] [.1CE0.0020.0008]
èD => [.1D10.0020.0002] [.0000.0025.0002] [.1CF5.0020.0008]
êE => [.1D10.0020.0002] [.0000.0027.0002] [.1D10.0020.0008]
ēF => [.1D10.0020.0002] [.0000.0032.0002] [.1D4B.0020.0008]

3 단계 : 양식 정렬 키

eA => 1D10 1CAD 0000 0020 0020 0000 0002 0008
éB => 1D10 1CC6 0000 0020 0024 0020 0000 0002 0002 0008
ëC => 1D10 1CE0 0000 0020 002B 0020 0000 0002 0002 0008
èD => 1D10 1CF5 0000 0020 0025 0020 0000 0002 0002 0008
êE => 1D10 1D10 0000 0020 0027 0020 0000 0002 0002 0008
ēF => 1D10 1D4B 0000 0020 0032 0020 0000 0002 0002 0008

4 단계 : 정렬 키 비교 : 두 번째 값은 모두 정렬하기에 충분하며 실제로 이미 증가하는 순서이므로 최종 순서는 실제로 다음과 같습니다.

eA
éB
ëC
èD
êE
ēF

업데이트 : Solomon Rutzky 세 번째 사례 추가 : 새로운 규칙을 사용할 수있는 공간 때문에 까다로워졌습니다 ( "무시할 수없는 사례"를 선택했습니다).

1 단계, NFD :

è 1 => U+0065 U+0300 U+0020 U+0031
ê 5 => U+0065 U+0302 U+0020 U+0035
e 2 => U+0065 U+0020 U+0032
é 4 => U+0065 U+0301 U+0020 U+0034
ē 3 => U+0065 U+0304 U+0020 U+0033
ë 6 => U+0065 U+0308 U+0020 U+0036

2 단계, 콜 레이션 배열 생성 :

è 1 => [.1D10.0020.0002] [.0000.0025.0002] [*0209.0020.0002] [.1CA4.0020.0002]
ê 5 => [.1D10.0020.0002] [.0000.0027.0002] [*0209.0020.0002] [.1CA8.0020.0002]
e 2 => [.1D10.0020.0002] [*0209.0020.0002] [.1CA5.0020.0002]
é 4 => [.1D10.0020.0002] [.0000.0024.0002] [*0209.0020.0002] [.1CA7.0020.0002]
ē 3 => [.1D10.0020.0002] [.0000.0032.0002] [*0209.0020.0002] [.1CA6.0020.0002]
ë 6 => [.1D10.0020.0002] [.0000.002B.0002] [*0209.0020.0002] [.1CA9.0020.0002]

3 단계, 양식 정렬 키 :

è 1 => 1D10 0209 1CA4 0000 0020 0025 0020 0020 0000 0002 0002 0002 0002
ê 5 => 1D10 0209 1CA8 0000 0020 0027 0020 0020 0000 0002 0002 0002 0002
e 2 => 1D10 0209 1CA5 0000 0020 0020 0020 0000 0002 0002 0002
é 4 => 1D10 0209 1CA7 0000 0020 0024 0020 0020 0000 0002 0002 0002 0002
ē 3 => 1D10 0209 1CA6 0000 0020 0032 0020 0020 0000 0002 0002 0002 0002
ë 6 => 1D10 0209 1CA9 0000 0020 002B 0020 0020 0000 0002 0002 0002 0002

4 단계, 정렬 키 비교 :

기본적으로 세 번째 값은 순서를 결정하며 실제로는 마지막 숫자만을 기준으로하므로 순서는 다음과 같아야합니다.

è 1
e 2
ē 3
é 4
ê 5
ë 6

유니 코드 버전에 대한 Solomon Rutzky의 의견을 기반으로 한 두 번째 업데이트 .

현재 allkeys.txt최신 유니 코드 버전, 즉 버전 10.0에 대한 데이터를 사용했습니다.

대신 유니 코드 5.1 을 고려해야하는 경우 다음과 같습니다. http://www.unicode.org/Public/UCA/5.1.0/allkeys.txt

위의 모든 문자에 대해 데이터 정렬 배열이 대신 다음과 같이 확인되었습니다.

e => [.119D.0020.0002.0065]
é => [.119D.0020.0002.0065] [.0000.0032.0002.0301]
ë => [.119D.0020.0002.0065] [.0000.0047.0002.0308]
è => [.119D.0020.0002.0065] [.0000.0035.0002.0300]
ê => [.119D.0020.0002.0065] [.0000.003C.0002.0302]
ē => [.119D.0020.0002.0065] [.0000.005B.0002.0304]

과:

eA => [.119D.0020.0002.0065] [.1141.0020.0008.0041]
éB => [.119D.0020.0002.0065] [.0000.0032.0002.0301] [.1157.0020.0008.0042]
ëC => [.119D.0020.0002.0065] [.0000.0047.0002.0308] [.116F.0020.0008.0043]
èD => [.119D.0020.0002.0065] [.0000.0035.0002.0300] [.1182.0020.0008.0044]
êE => [.119D.0020.0002.0065] [.0000.003C.0002.0302] [.119D.0020.0008.0045]
ēF => [.119D.0020.0002.0065] [.0000.005B.0002.0304] [.11D5.0020.0008.0046]

과:

è 1 => [.119D.0020.0002.0065] [.0000.0035.0002.0300] [*0209.0020.0002.0020] [.1138.0020.0002.0031]
ê 5 => [.119D.0020.0002.0065] [.0000.003C.0002.0302] [*0209.0020.0002.0020] [.113C.0020.0002.0035]
e 2 => [.119D.0020.0002.0065] [*0209.0020.0002.0020] [.1139.0020.0002.0032]
é 4 => [.119D.0020.0002.0065] [.0000.0032.0002.0301] [*0209.0020.0002.0020] [.113B.0020.0002.0034]
ē 3 => [.119D.0020.0002.0065] [.0000.005B.0002.0304] [*0209.0020.0002.0020] [.113A.0020.0002.0033]
ë 6 => [.119D.0020.0002.0065] [.0000.0047.0002.0308] [*0209.0020.0002.0020] [.113D.0020.0002.0036]

그런 다음 다음 정렬 키로 계산합니다.

e => 119D 0000 0020 0000 0002 0000 0065
é => 119D 0000 0020 0032 0000 0002 0002 0000 0065 0301
ë => 119D 0000 0020 0047 0000 0002 0002 0000 0065 0308
è => 119D 0000 0020 0035 0000 0002 0002 0000 0065 0300
ê => 119D 0000 0020 003C 0000 0002 0002 0000 0065 0302
ē => 119D 0000 0020 005B 0000 0002 0002 0000 0065 0304

과:

eA => 119D 1141 0000 0020 0020 0000 0002 0008 0000 0065 0041
éB => 119D 1157 0000 0020 0032 0020 0000 0002 0002 0008 0000 0065 0301 0042
ëC => 119D 116F 0000 0020 0047 0020 0000 0002 0002 0008 0000 0065 0308 0043
èD => 119D 1182 0000 0020 0035 0020 0000 0002 0002 0008 0000 0065 0300 0044
êE => 119D 119D 0000 0020 003C 0020 0000 0002 0002 0008 0000 0065 0302 0045
ēF => 119D 11D5 0000 0020 005B 0020 0000 0002 0002 0008 0000 0065 0304 0046

과:

è 1 => 119D 0209 1138 0000 0020 0035 0020 0020 0000 0002 0002 0002 0002 0000 0065 0300 0020 0031
ê 5 => 119D 0209 113C 0000 0020 003C 0020 0020 0000 0002 0002 0002 0002 0000 0065 0302 0020 0035
e 2 => 119D 0209 1139 0000 0020 0020 0020 0000 0002 0002 0002 0000 0065 0020 0032
é 4 => 119D 0209 113B 0000 0020 0032 0020 0020 0000 0002 0002 0002 0002 0000 0065 0301 0020 0034
ē 3 => 119D 0209 113A 0000 0020 005B 0020 0020 0000 0002 0002 0002 0002 0000 0065 0304 0020 0033
ë 6 => 119D 0209 113D 0000 0020 0047 0020 0020 0000 0002 0002 0002 0002 0000 0065 0308 0020 0036

이 세 가지 정렬 된 결과가 다시 나타납니다.

e
é
è
ê
ë
ē

eA
éB
ëC
èD
êE
ēF

è 1
e 2
ē 3
é 4
ê 5
ë 6

패트릭 안녕하세요. 자세한 정보를 게시 해 주셔서 감사합니다. 몇 가지 참고 사항 : 1) Code Page 1252를 무시할 수 있습니다 VARCHAR. 여기서는 사용되지 않는 유니 코드가 아닌 데이터 용입니다. 그래서 ē캐릭터가 잘 작동합니다. 2) "collation-charts"정보는 약간 구식입니다. 이 Collation의 이전 버전을위한 것이며 2009 년 이후로 아무것도 게시하지 않았습니다. 3) 여기서 유니 코드 버전은 확실히 최신 버전이 아닙니다 (버전 10). _100_이 유니 코드 5.0 또는 5.1 될 수 있도록 일련의 데이터 정렬은 SQL 2008와 함께 unicode.org/standard/versions/#TUS_Earlier_Versions
솔로몬 Rutzky

allKeys.txt 새 문자를 추가하는 것 외에도 유니 코드 버전 사이 의 변경 사항을 생각하지 않으므로 위의 내용을 그대로 유지해야하지만 물론 이전의 이전 데이터로 다시 실행할 수 있습니다. 몇 시간 동안 다시 넣는 에너지가 부족합니다. CP1252는 MS-SQL에서 제공 한 정의에서 나온 것입니다 (이 제품을 직접 사용하지는 않습니다).
Patrick Mevzek 4

1) 버전간에 큰 변화는 없을 것 같지만 최소한 무게 / 분류 수정이 있다고 확신합니다. 그러나 예, 확실히 시간 제약이 있습니다.) 2) CP1252와 관련하여 코드 페이지 개념이 유니 코드 내에 존재하지 않기 때문에 언급했습니다. 유니 코드는 코드 페이지가 필요하지 않은 수단입니다. MS 문서는 이것에 대해 분명하지 않지만, " 유니 코드가 아닌 문자 데이터를 저장하는 데 사용되는 코드 페이지 "맨 위에 언급 되어 있습니다 . CP1252에는 한 문자가 없지만 코드 페이지는 여기에서 재생되지 않습니다.
Solomon Rutzky

예, 유니 코드와 관련된 코드 페이지에 대해서는 언급하지 않았습니다. 이 데이터 정렬 이름이 "코드 페이지 1252"로 작동한다고 말하는 것은 MS SQL 문서 일뿐입니다. 아마 이해가되지 않을 것입니다 (나에게는 그렇지 않지만 다시는 사용자가 아닙니다).하지만이 소프트웨어의 문서에 쓰여 있습니다. 작업을 다시 실행하는 경우 자유롭게 수행하거나 유니 코드 5 이상에서 필요한 경우 여기에서 재생중인 문자와 관련된 정렬에 대한 변경 사항을 제공하십시오. 나는 내 대답이 그대로 있고 정확하고 다른 방법이 아닌 입력을 기반으로 결과를 작성한다고 믿습니다.
Patrick Mevzek

3) re : 문장 # 1 : 대부분 유니 코드에 관한 것이지만,이 질문은 MS가 사양을 구현하고 모든 것을 수행하지 않았거나 실수를 범했을 수 있으므로 OS 문제입니다. .NET에서 특정 문자가있는 "범주"또는 "블록"을 결정하는 방법과 관련하여 2 개의 버그가 발견되었습니다 (작은 문자 세그먼트를 잘못 식별 함). 또한,이 입니다 그들은 지금 SQL Server 관련 행동이 무엇인지 할 수 있도록 SQL 서버 (버전 사이의 일관성) 시점에서 각 정렬의 효율적 스냅 샷이있는 경우에만 있기 때문에, 약간 이상에서, SQL 서버 문제를 해결합니다.
Solomon Rutzky

16

여기에서보고있는 행동은 일반적으로 UCA (Unicode Collation Algorithm) 는 복잡한 다중 레벨 정렬이 가능하기 입니다. 더 구체적으로:

  1. 정렬은 비교가 아닙니다 :

    두 문자열이 같은지 다른지를 결정하는 것은 상당히 간단합니다 (특정 로케일 / 언어 및 감도 세트가 제공됨). 그러나 2 개 이상의 문자열 순서를 결정하는 것은 매우 복잡 할 수 있습니다.

  2. 정렬은 일련의 단계로 수행되며 각 단계는 문자 별이 아닌 전체 문자열에 적용됩니다.

    1. 표준 : 기본 문자 정렬 (강조 및 대소 문자 차이에 관계없이)
    2. 악센트에 민감한 경우 악센트 / 분음 부호를 적용합니다
    3. 대 / 소문자를 구분하는 경우 케이싱 무게를 적용하십시오

col1(단일 문자) 를 기준으로 정렬하면 모든 문자가 모두 " e " 이므로 모든 문자의 가중치가 동일한 것으로 결정합니다 . 다음으로 악센트 / 분음 부호를 적용합니다. 케이싱 차이가 없으므로 세 번째 단계는 아무 것도 변경하지 않습니다. 따라서 2 단계의 유일한 차이점은 다음을 기준으로 해당 행에 우선 순위가있는 이유입니다.col1 .

col2두 문자로 정렬 할 때는 두 문자가 모두 정렬 가중치를 결정하는 데 사용되므로 (예 : " ea ", " eb "등) 각 행의 가중치가 다른지 먼저 결정합니다 . 다음으로 악센트 / 분음 부호를 적용합니다. 케이싱 차이가 없으므로 세 번째 단계는 아무 것도 변경하지 않습니다. 이번에는 1 단계와 2 단계에 차이가 있습니다. 그러나 2 단계의 가중치를 고려하기 전에 1 단계의 차이점이 각 문자열에 이미 적용되었으므로 2 단계의 가중치는 순서에 영향을 미치지 않습니다. 둘 이상의 행에 대한 1 단계의 가중치가 동일한 경우에만 적용됩니다.

질문의 샘플 코드에 대한 다음의 적응은 위에서 설명한 정렬 동작을 잘 보여줍니다. Collation이 대소 문자를 구분하는 영향을 보여주기 위해 몇 개의 행과 열을 추가했습니다 (원래 샘플 데이터가 모두 소문자이므로).

설정

USE [tempdb];

-- DROP TABLE dbo.OddSort;
CREATE TABLE dbo.OddSort
(
    id INT IDENTITY(1,1) PRIMARY KEY,
    col1 NVARCHAR(5) COLLATE Latin1_General_100_CS_AS,
    col2 NVARCHAR(5) COLLATE Latin1_General_100_CS_AS,
    col3 NVARCHAR(5) COLLATE Latin1_General_100_CS_AS
);
GO

INSERT dbo.OddSort (col1, col2, col3)
VALUES (N'e', N'eA', N'e A')
     , (N'ê', N'êE', N'ê E')
     , (N'é', N'éH', N'é H')
     , (N'ë', N'ëC', N'ë C')
     , (N'E', N'EG', N'E G')
     , (N'Ë', N'ëh', N'ë h')
     , (N'è', N'èD', N'è D')
     , (N'é', N'éB', N'é B')
     , (N'ë', N'ëH', N'ë H')
     , (N'ē', N'ēF', N'ē F');

테스트 1

SELECT [id], [col1], UNICODE([col1]) AS [CodePoint]
FROM dbo.OddSort 
ORDER BY col1;

보고:

id    col1    CodePoint
1     e       101
5     E       69
8     é       233
3     é       233
7     è       232
2     ê       234
4     ë       235
9     ë       235
6     Ë       203
10    ē       275

위 결과에서 볼 수있는 것 :

  1. 코드 포인트가 정렬 순서를 결정하지 않습니다
  2. 악센트가없는 문자는 악센트 부호가있는 문자보다 먼저 정렬됩니다 (동일한 문자 내에서 f 는 여전히 모든 문자 뒤에옵니다). 분명히, 케이스 웨이트 전에 액센트 웨이트가 적용됩니다.
  3. 소문자는 동일한 악센트 부호가 붙은 (또는 강조되지 않은) 문자 내에서 대문자보다 먼저 정렬됩니다 (즉, e 다음에 E , ë 다음 Ë ). 이 조정은 대부분의 Windows 데이터 정렬에서 사용되며 대부분의 SQL Server 데이터 정렬은 대문자를 먼저 정렬합니다.

테스트 2

SELECT [id], [col2]
FROM dbo.OddSort 
ORDER BY col2;

보고:

id    col2
1     eA
8     éB
4     ëC
7     èD
2     êE
10    ēF
5     EG
3     éH
6     ëh
9     ëH

위 결과에서 볼 수있는 것 :

  1. 1 단계 정렬은 기본 문자입니다. 악센트 / 분음 부호 인 경우 ëC (id = 4), ēF (id = 10) 및 EG (id = 5) 행은 원래 위치에 있지 않습니다. 케이싱 인 경우 EG (id = 5) 행이 원래 위치에 있지 않습니다.
  2. 2 단계 분류는 실제로 악센트 / 분음 부호입니다. 마지막 세 행은 이유가 설명 EH -> EH -> EH 대신 EH -> EH -> EH (즉 ID를 3 -> 6 -> 9 대신 6 -> 3 -> 9).
  3. 3 단계 정렬은 실제로 케이싱입니다. 소문자가 먼저 정렬되므로 마지막 두 행이 ëh- > ëH 인 이유입니다.

테스트 3

SELECT [id], [col3]
FROM dbo.OddSort 
ORDER BY col3;

보고:

id    col3
1     e A
8     é B
4     ë C
7     è D
2     ê E
10    ē F
5     E G
3     é H
6     ë h
9     ë H

위 결과에서 볼 수있는 것 :

  1. 정렬 순서는 테스트 2와 정확히 동일합니다. 여기서 테스트 값의 유일한 차이점은 각 문자 사이에 공백이있어서 상황 별 규칙의 가능성을 제거한다는 것입니다. 따라서, 우리 col2는 질문 에서 정렬 순서의 차이에 대한 이유 가 "상황 민감도"가 아니라 " 다중 레벨 비교"에 기인 한다는 것을 알고 있습니다.

추가 사항 :

  1. 정확한 규칙을 얻는 것과 관련해서는 쉽지 않습니다. 이러한 규칙에 대한 구체적인 설명을 얻는 데있어 문제점은 확실하게 문서화되어 있지만 유니 코드 정렬 규칙이 권장 사항이라는 것입니다. 이러한 권장 사항을 구현하는 것은 Microsoft와 같은 공급 업체의 책임입니다. Microsoft는 유니 코드 문서에 명시된대로 권장 사항을 정확하게 구현하지 않았으므로 연결이 끊어졌습니다 (HTML 또는 CSS 사양이 공급 업체에서 완전히 또는 같은 방식으로 구현되는 방식과 유사 함). 그런 다음 여러 버전의 Windows 데이터 정렬 ( 100SQL Server 2008과 함께 제공되는 버전 을 사용 중)이 있으며 이는 현재 버전의 유니 코드 또는 ICU 데이터 정렬 데모 보다 훨씬 오래된 유니 코드 버전과 연결되어 있습니다.사용하고 있습니다. 예를 들어, SQL Server 2008 에 대한 "데이터 정렬 및 유니 코드 지원"설명서SQL Server 2008 데이터 정렬의 새로운 기능 섹션에서는 데이터 정렬_100_ 시리즈의 "새로운"기능에 대해 두 가지 흥미로운 점이 있습니다 .

    1. 유니 코드 5.0 사례 테이블.

      유니 코드 5.0은 2006 년 7 월에 출판되었습니다 (글자 데이터베이스는 공개되었고 2006 년 말에 전체 사양이 발표되었습니다). 현재 버전은 10.0이며 2017 년 6 월에 게시되었습니다. 지난 4 년의 릴리스 패턴을 고려할 때 2018 년 중반에 11.0 버전이 출시 될 가능성이 있습니다.

    2. 동일하게 비교되었던 이전의 비가 중 문자에 가중치가 추가되었습니다.

      이러한 가중치는 유니 코드 표준에서 정의 된 것보다 훨씬 높았습니다.

     
    여전히 위에 링크 된 UCA 문서는 시작하기에 좋은 곳입니다.

  2. Windows / .NET / SQL Server에서 사용하는 정렬 키는 유니 코드 표준 (@Patrick의 답변 참조)에 표시된 것과 동일하거나 ICU에 구현되어 있지 않습니다 . Windows / .NET / SQL Server가 무엇을 사용하는지 보려면 CompareInfo.GetSortKey Method를 사용해보십시오 . 이 값을 전달하고 정렬 키를 얻기 위해 SQLCLR UDF를 작성했습니다. .NET Framework 4.5-4.6.1이 설치된 Windows 10에서 SQL Server 2017을 사용하고 있으므로 .NET 유니 코드 6.0.0을 사용해야 합니다. 또한 레벨 4는이 문자열에 사용되지 않습니다.

    CHAR    L1     L2     L3     L4
    e      0E21
    E      0E21           12
    ë      0E21    13
    Ë      0E21    13     12

    테스트 1에 대한 이러한 정렬 키를보고 한 레벨 내에서 레벨이 여러 열처럼 정렬됨을 인식한다는 것 ORDER BY(L3은 동일한 L2의 값으로 정렬 됨, L1의 동일한 값으로 정렬 됨)은 동작의 이유를 설명해야합니다. 문제는 실제로 유니 코드의 다중 레벨 정렬 기능입니다. 마찬가지로:

    CHAR       L1         L2       L3       L4
    EG      0E210E25              1212
    éH      0E210E2C      0E      0212
    ëh      0E210E2C      13
    ëH      0E210E2C      13      0212

    테스트 2의 정렬 키 중 일부를 보면 기본 문자가 먼저 정렬 된 다음 (L1) 악센트가 정렬 된 다음 (L2) 케이싱이 정렬 됨 (L3)을 알 수 있습니다.

  3. 데이터 유형이이므로 NVARCHAR유니 코드 코드 포인트 및 정렬 알고리즘에만 관심이 있으므로 UNICODE()TEST 1 에서 함수를 사용합니다 . 코드 페이지는 대부분의 데이터 정렬에 의해 지정되지만 VARCHAR데이터 에만 관련됩니다 . 코드 페이지 1252는 Latin1_General*일련의 데이터 정렬로 지정되지만 여기서 무시할 수 있습니다.

  4. 기본 유니 코드 데이터 정렬 요소 테이블 (DUCET) ( 버전 5.0.0_100_데이터 정렬 시리즈에 맵핑되어야 함)에 설명 된 가중치는 미국 영어에는 적합하지만 다른 로케일 / 언어에는 적합하지 않습니다. 다른 언어는 필요가 시작 DUCET으로 다음 일반 로켈 데이터 리포지토리 (CLDR) 프로젝트에 의해 정의 된 로케일 고유의 재정 규칙을 적용합니다. 내가 알 수 있듯이, 버전 1.4 / 1.4.1은 2006 년에 출시되었습니다. 이러한 재정의를 얻으려면 http://unicode.org/Public/cldr/1.4.0/core.zip을 통해 CLDR 1.4 "코어"파일을 다운로드하십시오. 그런 다음 해당 zip 파일에서 데이터 정렬 폴더 로 이동하여 사용중인 로케일에 해당하는 XML 파일을 찾으십시오. 이러한 파일에는 재정의 만 포함되어 있으며 완전한 조합 규칙 세트가 아닙니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.