하나의 "문자"(여러 코드 포인트로 구성 될 수 있음 : 서로 게이트 쌍, 문자 결합 등)가 다른 규칙과 비교되는 방식은 다소 복잡한 규칙을 기반으로합니다. 유니 코드 사양에 표시된 모든 언어에서 발견되는 다양한 (때로는 "엉뚱한") 규칙을 모두 고려해야하기 때문에 너무 복잡 합니다. 이 시스템은 모든 NVARCHAR
데이터와 VARCHAR
SQL Server 데이터 정렬이 아닌 Windows 데이터 정렬을 사용하는 데이터 (로 시작하는 데이터)에 대해 이진이 아닌 데이터 정렬에 적용됩니다 SQL_
. 이 시스템은 VARCHAR
간단한 매핑을 사용하므로 SQL Server 데이터 정렬을 사용하는 데이터 에는 적용되지 않습니다 .
대부분의 규칙은 UCA (Unicode Collation Algorithm)에 정의되어 있습니다. 이러한 규칙 중 일부와 UCA에서 다루지 않은 규칙은 다음과 같습니다.
allkeys.txt
파일에 제공된 기본 주문 / 무게 (아래에 표시)
- 어떤 민감도 및 옵션이 사용되고 있습니까 (예 : 대소 문자를 구분합니까? 아니면 대소 문자를 구분합니까?, 민감한 경우 대문자가 먼저 소문자입니까?)
- 모든 로캘 기반 재정의
- 유니 코드 표준 버전이 사용 중입니다.
- "인간"요소 (즉, 유니 코드는 소프트웨어가 아닌 사양이므로이를 구현하기 위해 각 공급 업체에 맡겨집니다)
휴먼 팩터에 관한 최종 요점은 SQL Server가 사양에 따라 항상 100 % 동작 할 것으로 기 대해서는 안된다는 점을 분명히하기 위해 강조했습니다.
여기서 가장 중요한 요소는 각 코드 포인트에 부여 된 가중치와 여러 코드 포인트가 동일한 가중치 사양을 공유 할 수 있다는 사실입니다. 여기에서 기본 가중치 (로케일 별 재정의 없음)를 찾을 수 있습니다 ( 100
일련의 데이터 정렬은 유니 코드 v 5.0- Microsoft Connect 항목 에 대한 주석의 비공식적 인 확인 이라고 생각합니다 ).
http://www.unicode.org/Public/UCA/5.0.0/allkeys.txt
해당 코드 포인트 – U + FFFD –는 다음과 같이 정의됩니다.
FFFD ; [*0F12.0020.0002.FFFD] # REPLACEMENT CHARACTER
이 표기법은 UCA의 9.1 Allkeys 파일 형식 섹션에 정의되어 있습니다 .
<entry> := <charList> ';' <collElement>+ <eol>
<charList> := <char>+
<collElement> := "[" <alt> <weight> "." <weight> "." <weight> ("." <weight>)? "]"
<alt> := "*" | "."
Collation elements marked with a "*" are variable.
우리가보고있는 코드 포인트에는 실제로 "*"로 시작하는 사양이 있으므로 마지막 줄이 중요합니다. 3.6 가변 가중치 섹션 에는 직접 액세스 할 수없는 데이터 정렬 구성 값을 기반으로 정의 된 네 가지 가능한 동작이 있습니다 (대소 문자 구분이 소문자인지 먼저 사용되는지와 같이 각 데이터 정렬의 Microsoft 구현에 하드 코딩 됨). 먼저 대문자를 VARCHAR
사용합니다. SQL_
데이터 정렬을 사용하는 데이터와 다른 모든 변형 이 다른 속성 ).
나는 어떤 경로가 취해 졌는지에 대한 완전한 연구를 수행하고 더 확실한 증거가 제공되도록 어떤 옵션이 사용되고 있는지 추론 할 시간이 없지만, 각 코드 포인트 사양 내에서 무언가에 관계없이 말할 수 있습니다. "동일한"것으로 간주되는 것은 항상 전체 사양을 사용하지는 않습니다. 이 경우, 우리는 "0F12.0020.0002.FFFD"를 가지고 있으며 아마도 사용중인 레벨 2와 3 일 것입니다 (예 : .0020.0002. ). 메모장에서 ".0020.0002"에 "카운트"를 수행합니다. 12,581 개의 일치 항목을 찾습니다 (아직 처리하지 않은 보조 문자 포함). "[*"에서 "Count"를 수행하면 4049 개의 일치 항목이 리턴됩니다. 패턴을 사용하여 RegEx "찾기"/ "카운트"수행\[\*\d{4}\.0020\.0002
832 개의 일치 항목을 반환합니다. 따라서이 조합의 어딘가에 내가 볼 수없는 다른 규칙과 Microsoft 특정 구현 세부 정보 가이 동작에 대한 전체 설명입니다. 분명히 말하면, 규칙이 적용되면 모두 동일한 가중치를 갖기 때문에 모든 일치하는 문자에 대해 동작이 동일합니다. 반드시 Mr. �
).
COLLATE
아래 쿼리를 통해 두 가지 버전의 데이터 정렬에서 다양한 감도가 어떻게 작동하는지 쿼리 아래 결과에 따라 절을 변경할 수 있습니다 .
;WITH cte AS
(
SELECT TOP (65536) ROW_NUMBER() OVER (ORDER BY (SELECT 0)) - 1 AS [Num]
FROM [master].sys.columns col
CROSS JOIN [master].sys.objects obj
)
SELECT cte.Num AS [Decimal],
CONVERT(VARBINARY(2), cte.Num) AS [Hex],
NCHAR(cte.Num) AS [Character]
FROM cte
WHERE NCHAR(cte.Num) = NCHAR(0xFFFD) COLLATE Latin1_General_100_CS_AS_WS --N'�'
ORDER BY cte.Num;
다른 데이터 정렬에서 일치하는 다양한 문자 수는 다음과 같습니다.
Latin1_General_100_CS_AS_WS = 5840
Latin1_General_100_CS_AS = 5841 (The "extra" character is U+3000)
Latin1_General_100_CI_AS = 5841
Latin1_General_100_CI_AI = 6311
Latin1_General_CS_AS_WS = 21,229
Latin1_General_CS_AS = 21,230
Latin1_General_CI_AS = 21,230
Latin1_General_CI_AI = 21,537
위에 나열된 모든 데이터 정렬 N'' = N'�'
에서 true로 평가됩니다.
최신 정보
좀 더 연구 할 수 있었고 여기에 내가 찾은 것이 있습니다.
"아마도"작동하는 방법
ICU 데이터 정렬 데모를 사용하여 로케일을 "en-US-u-va-posix"로 설정하고 강도를 "기본"으로 설정하고 "정렬 키"표시를 확인한 다음 위의 쿼리 결과 ( Latin1_General_100_CI_AI
Collation 사용) :
�
Ԩ
ԩ
Ԫ
그리고 그것은 다음을 반환합니다 :
Ԫ
60 2E 02 .
Ԩ
60 7A .
ԩ
60 7A .
�
FF FD .
그런 다음 http://unicode.org/cldr/utility/character.jsp?a=fffd 에서 " "의 문자 특성을 확인하고 레벨 1 정렬 키 (즉, FF FD
)가 "uca"특성과 일치하는지 확인하십시오. 해당 "uca"속성을 클릭하면 검색 페이지 ( http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3Auca%3DFFFD%3A%5D)로 이동 합니다. 또한 allkeys.txt 파일에서 레벨 1 정렬 가중치는로 표시되며 이에 0F12
대한 일치 항목은 1 개뿐입니다.
우리가 제대로 동작을 해석하고 있는지 확인하기 위해, 내가 다른 문자 보았다 : 그리스어 대문자 오 미크론 함께 VARIA Ὸ
에서 http://unicode.org/cldr/utility/character.jsp?a=1FF8 하는있는 "UCA"( 즉, 레벨 1 정렬 중량 / 배열 요소) 5F30
. "5F30"을 클릭하면 검색 페이지로 이동합니다 – http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3Auca%3D5F30%3A%5D – 30 개 일치, 20 개 중 20 개 표시 그것들은 0-65535 범위에 있습니다 (예 : U + 0000-U + FFFF). Code Point 1FF8 에 대한 allkeys.txt 파일을 살펴보면 레벨 1 정렬 가중치가입니다 . 메모장에서 "카운트"하기12E0
12E0.
30 개의 일치 항목을 표시합니다 (이 파일은 Unicode v 5.0 용이며 사이트에서 Unicode v 9.0 데이터를 사용하므로 보장되지는 않지만 Unicode.org의 결과와 일치 함).
SQL Server에서 다음 쿼리는 10 개의 보충 문자를 제거 할 때 Unicode.org 검색과 동일한 20 개의 일치 항목을 반환합니다.
;WITH cte AS
(
SELECT TOP (65535) ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS [Num]
FROM [master].sys.columns col
CROSS JOIN [master].sys.objects obj
)
SELECT cte.Num AS [Decimal],
CONVERT(VARCHAR(50), CONVERT(VARBINARY(2), cte.Num), 2) AS [Hex],
NCHAR(cte.Num) AS [Character]
FROM cte
WHERE NCHAR(cte.Num) = NCHAR(0x1FF8) COLLATE Latin1_General_100_CI_AI
ORDER BY cte.Num;
그리고 ICU 데이터 정렬 데모 페이지로 돌아가서 "입력"상자의 문자를 SQL Server의 20 개 결과 목록에서 가져온 다음 3 개의 문자로 바꾸십시오.
Ὂ
𝜪
Ὸ
실제로는 모두 동일한 5F 30
레벨 1 정렬 가중치를 갖습니다 (캐릭터 속성 페이지의 "uca"필드와 일치).
따라서이 특정 캐릭터가 다른 것과 일치 해서는 안되는 것처럼 보입니다 .
실제로 작동하는 방식 (적어도 Microsoft-land)
SQL Server와 달리 .NET에는 CompareInfo.GetSortKey 메서드 를 통해 문자열의 정렬 키를 표시하는 방법이 있습니다. 이 방법을 사용하고 U + FFFD 문자 만 전달하면 정렬 키가 반환 0x0101010100
됩니다. 그런 다음 0-65535 범위의 모든 문자를 반복하여 0x0101010100
4529 개의 일치 하는 정렬 키가있는 문자를 확인하십시오 . 이것은 Latin1_General_100_CS_AS_WS
데이터 정렬을 사용할 때 SQL Server에서 반환 된 5840과 정확히 일치하지 않지만 유니 코드 v를 사용하는 Windows 10 및 .NET Framework 버전 4.6.1을 실행 중이라면 지금 가장 가깝습니다. CharUnicodeInfo 클래스 의 차트에 따른 6.3.0( "설명"섹션의 "발신자 메모"). 현재 SQLCLR 함수를 사용하고 있으므로 대상 Framework 버전을 변경할 수 없습니다. 기회가되면 콘솔 응용 프로그램을 만들고 유니 코드 v 5.0을 사용하는 대상 Framework 버전 4.5를 사용합니다 .100 버전은 Collations와 일치해야합니다.
이 테스트는 U + FFFD에 대해 .NET과 SQL Server간에 정확히 같은 수의 일치 항목이 없어도 이것이 SQL Server 관련 동작 이 아니며 구현에 대한 의도적이든 감독이든 확실 하지 않음 을 보여줍니다. Microsoft에서 U + FFFD 문자는 유니 코드 사양에 맞지 않아도 실제로 몇 문자와 일치합니다. 그리고이 문자가 U + 0000 (null)과 일치하면 가중치가 누락 된 것일 수 있습니다.
또한
=
쿼리와 쿼리의 동작의 차이 LIKE N'%�%'
와 관련하여 와일드 카드 및 이러한 � Ƕ Ƿ Ǹ
문자 (예 :)의 누락 된 가중치와 관련이 있습니다. LIKE
조건이 단순히 상태로 변경 되면 조건 LIKE N'�'
과 동일한 3 행을 리턴합니다 =
. 와일드 카드 관련 문제가 "누락 된"가중치로 인한 것이 아닌 경우 ( btw에 0x00
의해 정렬 키가 반환 되지 않음) 정렬 키 CompareInfo.GetSortKey
가 컨텍스트 (예 : 주변 문자)에 따라 달라질 수있는 특성을 가진 문자가 잠재적으로있을 수 있습니다. ).
FFFD
(*0F12.0020.0002.FFFD
하나만 검색 하면 결과가 반환 됨). @Forrest의 관찰에서 그것들은 모두 빈 문자열과 일치하고 주제에 대한 조금 더 많은 독서는 다양한 비 이진 데이터 정렬에서 공유하는 가중치처럼 보입니다.