N'Șc '는 Latin1_General_CI_AS 데이터 정렬을 사용하여 N'C'의 중복 키로 간주


11

NVARCHAR(50)열 을 포함하는 고유 키가있는 테이블이 있습니다 (올바르거나 그렇지 않지만 있습니다). 따라서 삽입을 시도 Șc하거나 C( 삽입 순서와 상관없이) 삽입 문제로 인해 두 번째 삽입에서 파손됩니다. 오류는 다음과 같습니다.

(1 개의 행 영향을 받음) 메시지 2601, 수준 14, 상태 1, 줄 16 고유 인덱스 'IX_TestT'를 사용하여 'dbo.testT'개체에 중복 키 행을 삽입 할 수 없습니다. 중복 키 값은 (C)입니다.

반품 선택 :

여기에 이미지 설명을 입력하십시오

데이터베이스 기본 데이터 정렬은 Latin1_General_CI_AS입니다. 기존 구조를 너무 많이 변경하지 않고 해결 방법을 찾는 데 시간을 보냈지 만 작업 방법을 찾지 못했습니다. 다른 데이터 정렬 및 조합을 시도했지만 모든 것이 실패합니다. 문자 확장 등에 대해 ( herehere ) 읽고 여전히 붙어 있습니다. 다음은 문제를 복제하는 데 사용하는 샘플 코드입니다.이 문제를 해결하는 데 도움이되는 것을 자유롭게 수정하고 추천하십시오.

CREATE TABLE testT (
    [Default_Collation]     [NVARCHAR] (50) COLLATE DATABASE_DEFAULT,
    [Latin1_General_CI_AS]  [NVARCHAR] (50) COLLATE Latin1_General_CI_AS,
    [Latin1_General_CI_AI]  [NVARCHAR] (50) COLLATE Latin1_General_CI_AI,
    [SQL_Collation]         [NVARCHAR] (50) COLLATE SQL_Latin1_General_CP1_CI_AS);
CREATE UNIQUE CLUSTERED INDEX [IX_TestT] ON [dbo].[testT] ([Default_Collation])
ON [PRIMARY]
GO

INSERT INTO testT
SELECT  N'Șc',  --COLLATE Latin1_General_CI_AS
        N'Șc',  --COLLATE Latin1_General_CI_AS
        N'Șc',  --COLLATE Latin1_General_CI_AS
        N'Șc'   --COLLATE Latin1_General_CI_AS

INSERT INTO testT
SELECT  N'C'    --COLLATE Latin1_General_CI_AS 
        ,N'C'   --COLLATE Latin1_General_CI_AS
        ,N'C'   --COLLATE Latin1_General_CI_AS
        ,N'C'   --COLLATE SQL_Latin1_General_CP1_CI_AS

SELECT * FROM testT;

DROP TABLE testT;

답변:


10

문제는 이전 SQL Server 데이터 정렬 (예 : 이름으로 시작하는 이름 SQL_)과 Windows 데이터 정렬의 첫 두 버전 ( 80SQL Server 2000과 함께 제공되고 이름에 버전 번호가없는 90시리즈)과 SQL Server 2005와 함께 제공됨)에는 많은 문자에 대한 정렬 가중치가 누락되었습니다. 이것은 주로 100SQL Server 2008과 함께 제공된 시리즈 데이터 정렬로 시작하여 수정되었습니다 .

아래 예제에서 볼 수 있듯이 Ș이진이 아닌 버전 80 또는 90 데이터 정렬 (및 SQL Server 데이터 정렬)을 사용하는 경우 문자는 모두 동일한 정렬 가중치를 갖기 때문에 빈 문자열과 일치합니다. 0. Nothing. 나다. 이것은 (사전 시리즈 100 데이터 정렬 사용) N'Șc'과 비교할 때 N'C'실제로 (테스트 # 1) N'c'과 비교 하고 N'C'있음을 의미합니다.

SELECT 1 WHERE N'Șc' = N'C' COLLATE Latin1_General_CS_AS;
-- no result (due to "c" and "C" being different case)

SELECT 2 WHERE N'Ș' = N'' COLLATE SQL_Latin1_General_CP1_CI_AS;
SELECT 3 WHERE N'Ș' = N'' COLLATE Latin1_General_CI_AS;

SELECT 4 WHERE N'Ș' = N'' COLLATE Latin1_General_BIN2;
-- no result (due to "Ș" still being a code point and empty string has no code points)

SELECT 5 WHERE N'Ș' = N'' COLLATE Latin1_General_100_CI_AS;
-- no result (due to "Ș" finally having a sort weight in 100 series Collations)

SELECT 6 WHERE N'Ș' = N'' COLLATE Chinese_PRC_CI_AI;
SELECT 7 WHERE N'Ș' = N'' COLLATE Chinese_PRC_90_CI_AI;

SELECT 8 WHERE N'Ș' = N'' COLLATE Indic_General_90_CI_AI;
SELECT 9 WHERE N'Ș' = N'' COLLATE Indic_General_100_CI_AI;
-- no result (due to "Ș" finally having a sort weight in 100 series Collations)

따라서 불행히도 PK를 삭제하고 열을 100 수준 데이터 정렬 (예 :)로 변경 Latin1_General_100_CI_AS_SC한 다음 PK를 다시 만들어야합니다. 점에서 차이가 현재 데이터 정렬에서 정렬을 제안합니다 모두를 제발 100 하고_SC 제대로 보조 문자를 처리 할 수 있습니다 말에.

그렇다고 반드시 다음을 수행해야하는 것은 아닙니다 .

  1. 다른 테이블의 데이터 정렬을 변경합니다 ( NVARCHARPK에서 설정이 동일하지 않은 경우 )
  2. 데이터베이스의 기본 데이터 정렬을 변경하십시오. DB를의 데이터 정렬을 변경하지의 주된 문제는 수행 사이의 행동 차이가있을 것입니다 table.column = N'Ș'@variable = N'Ș'변수와 문자열 리터럴은 데이터베이스의 기본 데이터 정렬을 사용입니다.

이 동작에 대한 자세한 예는 다음 블로그 게시물의 "보충 문자"섹션을 참조하십시오.

The Uni-Code : T-SQL 식별자의 유효한 문자 목록 검색, 2/3 부 (구분 식별자)

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