@gbn은 이미 기본 이유와 수정을 설명했지만 현재보고있는 동작의 구체적인 이유는 다음과 같습니다.
- 당신은 사용하는
VARCHAR문자 (NO N접두사) 대신의 NVARCHAR문자 (와 문자열 N접두어), 따라서 유니 코드 문자로 변환되는 것이다 VARCHAR.
VARCHAR대부분의 경우 문자 당 1 바이트이지만 문자 당 2 바이트 일 수있는 8 비트 인코딩입니다. 반면에 NVARCHAR문자 당 2 바이트 또는 4 바이트 인 16 비트 인코딩 (UTF-16 Little Endian)입니다.
- 문자를 매핑하는 데 사용할 수있는 바이트 수의 차이로 인해 8 비트 인코딩은 그 특성상 매핑 할 수있는 문자 수가 훨씬 더 제한됩니다.
VARCHAR데이터는 1 바이트 문자 세트 (대부분)의 경우 최대 256 자이고 2 바이트 문자 세트 (대부분의 숫자)의 경우 최대 65,536 자입니다. 반면, NVARCHAR데이터는 110 만 개 이상의 유니 코드 문자를 매핑 할 수 있습니다 (현재 매핑 된 250k 미만).
- 8 비트 /
VARCHAR데이터 로 수행 할 수있는 매핑 수가 제한되어 있기 때문에 (언어 / 문화를 기반으로하는) 문자 그룹이 여러 "코드 페이지"(예 : 문자 세트)에 분산됩니다.
- 각 데이터 정렬은 데이터에 사용할 코드 페이지 (있는 경우)를 지정
VARCHAR합니다 ( NVARCHAR모든 문자 임)
- 문자열 리터럴 또는 변수를
NVARCHAR(예 : 유니 코드 / UTF-16 / 모든 문자)에서 VARCHAR(대부분의 데이터 정렬에 지정된 코드 페이지를 기반으로하는 문자 세트 )로 변환 할 때 데이터베이스의 기본 데이터 정렬이 사용됩니다
- 변환에 사용되는 데이터 정렬의 코드 페이지에 동일한 문자가 없지만 "최 적합"매핑이 포함 된 경우 "최 적합"매핑이 사용됩니다.
- 변환에 사용되는 데이터 정렬의 코드 페이지에 동일한 문자가 없거나 "가장 적합"매핑이 포함 된 경우 기본 "대체"문자가 사용됩니다 (가장 일반적으로
?).
그래서, 당신이보고있는 것은입니다 NVARCHAR로 VARCHAR인해 누락 변환을 N문자열 리터럴에 접두사. 그리고 데이터베이스에 대한 기본 데이터 정렬의 코드 페이지에 정확히 동일한 문자가 포함되어 있지 않지만 "최적의"매핑이 발견 되었기 때문에 . 2대신을 (를) 받고 ?있습니다.
다음과 같은 간단한 테스트를 수행하여이 효과를 볼 수 있습니다.
SELECT '₂', N'₂';
보고:
2 ₂
분명히 데이터베이스의 기본 데이터 정렬의 코드 페이지에 정확히 동일한 문자가 포함되어 있으면 해당 코드 페이지에서 동일한 문자로 변환 된 것입니다. 그런 다음 NVARCHAR열에 저장 하기 때문에 원래의 유니 코드 문자로 다시 변환되었을 것입니다. 아래의 마지막 예는이 동작을 보여줍니다.
중요 : 문자열 리터럴을 해석 할 때 열에 저장 되기 전에 변환이 수행됩니다. 이는 열이 해당 문자를 보유 할 수있는 경우에도 N해당 문자열 리터럴의 접 두부 를 생략하여 데이터베이스의 기본 데이터 정렬을 기반으로 이미 다른 문자로 변환되었음을 의미합니다. 그리고 이것은 정확히 당신이 경험 한 것입니다.
예를 들어, 데이터베이스의 기본 데이터 정렬이 한국어 데이터 정렬 중 하나 (4 개의 2 바이트 문자 집합 중 하나) 인 경우 해당 문자에서 "아래 첨자 2"문자를 사용할 수 있으므로이 문제를 보지 못했을 것입니다. 설정 (코드 페이지 949). 다음 테스트를 수행하여 확인하십시오 (데이터베이스의 기본 데이터 정렬 대신 열의 데이터 정렬을 사용하는 것이 더 쉽습니다).
CREATE TABLE #TestChar
(
[8bit_Latin1_General-1252] VARCHAR(2) COLLATE Latin1_General_100_CI_AS_SC,
[8bit_Korean-949] VARCHAR(2) COLLATE Korean_100_CI_AS_SC,
[UTF16LE_Latin1_General-1252] NVARCHAR(2) COLLATE Latin1_General_100_CI_AS_SC
);
INSERT INTO #TestChar VALUES (N'₂', N'₂', N'₂');
SELECT * FROM #TestChar;
보고:
8bit_Latin1_General-1252 8bit_Korean-949 UTF16LE_Latin1_General-1252
2 ₂ ₂
보다시피, 데이터에 Code Page 1252 ( Modern_SpanishCollations에서 사용 하는 것과 동일한 Code Page)를 사용하는 Latin1_General Collations VARCHAR는 정확히 일치하지는 않지만 " 최 적합"매핑 (현재보고있는 것)을 갖습니다. ). 그러나 데이터에 코드 페이지 949를 사용하는 한국어 데이터 정렬 VARCHAR은 "아래 첨자 2"문자와 정확히 일치합니다.
더 자세히 설명하기 위해 한국어 데이터 정렬 중 하나의 기본 데이터 정렬을 사용하여 새 데이터베이스를 만든 다음 질문에있는 정확한 SQL을 실행할 수 있습니다.
CREATE DATABASE [TestKorean-949] COLLATE Korean_100_CI_AS_KS_WS_SC;
ALTER DATABASE [TestKorean-949] SET RECOVERY SIMPLE;
GO
USE [TestKorean-949];
CREATE TABLE test (
id INT NOT NULL,
description NVARCHAR(100) COLLATE Modern_Spanish_CI_AS NOT NULL
);
INSERT INTO test (id, description) VALUES (1, 'CO2');
SELECT * FROM test WHERE id = 1;
UPDATE test SET description = 'CO₂' WHERE id = 1;
SELECT * FROM test WHERE id = 1;
보고:
id description
1 CO2
id description
1 CO₂
최신 정보
여기에서 정확히 무슨 일 이 일어나고 있는지에 대해 더 자세히 알고 싶은 사람은 방금 게시 한 두 부분으로 된 조사를 참조하십시오.