varchar 데이터 유형에 유니 코드 값이 허용되는 이유는 무엇입니까?


17

varchar 열이있는 테이블이 있습니다. 아래와 같이 상표 (™), 저작권 (©) 및 기타 유니 코드 문자를 사용할 수 있습니다.

Create table VarcharUnicodeCheck
(
col1 varchar(100)
)

insert into VarcharUnicodeCheck (col1) values ('MyCompany')
insert into VarcharUnicodeCheck (col1) values ('MyCompany™')
insert into VarcharUnicodeCheck (col1) values ('MyCompany░')
insert into VarcharUnicodeCheck (col1) values ('MyCompanyï')
insert into VarcharUnicodeCheck (col1) values ('MyCompany')

select * from VarcharUnicodeCheck

그러나 varchar정의는 유니 코드가 아닌 문자열 데이터를 허용한다고 말합니다. 그러나 상표 (™) 및 등록 (®) 기호는 유니 코드 문자입니다. 정의가 varchar 데이터 유형의 속성과 모순됩니까? 나는 첫 번째두 번째 와 같은 몇 가지 링크를 읽었습니다 . 그러나 정의에 유니 코드가 아닌 문자열 값만 허용한다고 말할 때 왜 유니 코드 문자열을 허용하는지 이해할 수 없었습니다.


12
모든 문자는 유니 코드 문자입니다.
Martin Smith

Microsoft는 종종 UTF-16 / UCS-2를 의미 할 때 UNICODE를 사용합니다. 따라서 유니 코드가 일부 컨텍스트이므로 UTF-8을 계산하지 않을 수도 있습니다.
코드 InChaos

1
@ CodesInChaos : 귀하의 의견을 파싱하는 데 어려움을 겪었지만 유니 코드를 다양한 UTF-n 인코딩과 혼동하고 있다고 걱정합니다.
가벼움 경주 Monica

1
@Martin Smith : 모든 문자가 유니 코드 문자 인 경우 왜 Microsoft varchar 정의 에서 유니 코드가 아닌 문자열 데이터를 허용한다고 말합니까?
시바

2
varchar의 문자 인코딩은 유니 코드가 아니지만 모든 문자가 유니 코드로 존재합니다
Martin Smith

답변:


15

그러나 상표 (™) 및 등록 (®) 기호는 유니 코드 문자입니다.

당신의 잘못입니다. 문자열은 ascii문자 만 포함합니다 .

다음은 문자가 모두 ASCII임을 나타내는 간단한 테스트입니다 (+ extended ascii128에서 255 사이의 ASCII 코드를 가진 일부 ).

declare @VarcharUnicodeCheck table
(
col1 varchar(100)
)

insert into @VarcharUnicodeCheck (col1) values ('MyCompany')
insert into @VarcharUnicodeCheck (col1) values ('MyCompany™')
insert into @VarcharUnicodeCheck (col1) values ('MyCompany░')
insert into @VarcharUnicodeCheck (col1) values ('MyCompanyï')
insert into @VarcharUnicodeCheck (col1) values ('MyCompany')

select *,
        right(col1, 1)as last_char, 
        ascii(right(col1, 1)) as_last_char_ascii
from @VarcharUnicodeCheck;

여기에서 모든 문자가 1 바이트로 인코딩되어 있음을 분명히 알 수 있습니다.

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

예, 그들은 순수한 ASCII 문자는 아니지만 확장 ASCII 입니다.

다음은 실제 유니 코드 문자 Trademark(™)와 해당 코드 및 이진 표현을 보여줍니다 .

declare @t table (uni_ch nchar(1), ascii_ch char(1));
insert into @t values (N'™', '™');

select unicode(uni_ch) as [unicode of ™], 
       ascii(ascii_ch) [ascii of ™], 
       cast(uni_ch as varbinary(10)) as [uni_ch as varbinary], 
       cast(ascii_ch as varbinary(10)) as [ascii_ch as varbinary]
from @t;

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

마지막으로 Trademark(™)유니 코드 문자에는 153이 아닌 8482 코드가 있음을 알 수 있습니다 .

select nchar(8482), nchar(153)

1
그러나 언급 한 기사에는 "ASCII"단어가 없으며, 유니 코드 및 비 유니 코드 문자에 대해서만 이야기하고 있으며 사용한 상표 (™)는 유니 코드가 아닙니다.
sepupic

16
"확장 ASCII"는 끔찍한 모호한 용어입니다. 실제로 사용되는 8 비트 인코딩을 확인하는 것이 더 도움이됩니다 (로케일 / 데이터 정렬 설정을 기반으로합니까?). Windows 코드 페이지 1252를 추측하고 있습니다. 실제로 ™를 문자 153으로 인코딩합니다.
IMSoP

2
@sepupic 코드 포인트와 인코딩의 차이점에 대해 더 읽어야한다고 생각합니다. Wikipedia 가 도움이 될 수 있습니다. "인코딩은 유니 코드 코드 의 범위를 코드 값이라고하는 일부 고정 크기 범위의 값 시퀀스에 매핑 합니다 . 8482는 Windows-1252에서 \ x99 (153), MacRoman에서 \ xAA, UTF-8에서 \ xE2 \ x84 \ xA2 등으로 인코딩 될 수있는 ™의 코드 포인트입니다.
curiousdannii

7
127보다 큰 8 비트 문자는주의해야합니다. 127보다 큰 각 코드가 나타내는 것은 사용중인 인코딩에 따라 달라질 수 있으며 사용중인 데이터 정렬에 따라 달라집니다. 코드 페이지 1252에서 유니 코드 8482는 153에 매핑됩니다. 코드 페이지 850에서 해당 지점은 214 ( Ö)에 의해 사용되고 ISO-8859-1 (때로는 Latin1이라고 함)에서는 인쇄 가능한 표현이없는 제어 코드입니다. 당신이하지 않는 알고 당신이됩니다 항상 같은 코드 페이지를 사용은 ANSI 문자 (127 이하) 또는 사용 유니 코드 형식에 충실하는 것이 안전하다. 코드 페이지 1252는 SQL Server에서 가장 일반적이지만 유비쿼터스와는 거리가 멀습니다.
David Spillett

4
@Shiva 절대 최소 모든 소프트웨어 개발자는 절대적으로 유니 코드 및 문자 집합에 대해 알아야 합니다. ASCII는 많은 인코딩 의 하위 집합 이며 거의 모든 인코딩은 ASCII가 아닌 기호를 포함하며 동시에 유니 코드가 아닙니다. 그리고 유니 코드에는 UTF-8, UTF-32 등과 같은 많은 다른 인코딩도 있습니다.
jpmc26

7

의견에서 "확장 ASCII"는 실제로 나쁜 용어이며 이는 실제로 ASCII로 정의 된 표준 0-127 코드 포인트 범위를 넘어 128-255 범위의 문자 / 코드 포인트를 매핑하는 코드 페이지를 의미합니다.

SQL Server는 데이터 정렬을 통해 많은 코드 페이지를 지원합니다. 기본 데이터 정렬이 문자를 지원하는 한 비 ASCII 문자는 varchar에 저장할 수 있습니다.

SQL Server 데이터 정렬 코드 페이지가 1250 이상인 경우 '™'문자를 varchar / char 열에 저장할 수 있습니다. 쿼리 아래에 다음이 나열됩니다.

SELECT COLLATIONPROPERTY(name, 'CodePage') AS code_page, name, description
FROM sys.fn_helpcollations()
WHERE COLLATIONPROPERTY(name, 'CodePage') >= 1250
ORDER BY name;

그러나 이들 중 일부만 '©'문자를 지원하므로 열 데이터 정렬은 다음 중 하나 여야합니다.

SELECT COLLATIONPROPERTY(name, 'CodePage') AS code_page, name, description
FROM sys.fn_helpcollations()
WHERE COLLATIONPROPERTY(name, 'CodePage') IN(
    1250
    ,1251
    ,1252
    ,1253
    ,1254
    ,1255
    ,1256
    ,1257
    ,1258
)
ORDER BY name;

4

그러나 varchar의 정의에 따르면 유니 코드가 아닌 문자열 데이터를 사용할 수 있습니다. 그러나 상표 (™) 및 등록 (®) 기호는 유니 코드 문자 입니다. 정의가 varchar 데이터 유형의 속성과 모순됩니까?

다른 답변은 정확하지 않지만 기본 용어의 혼란을 지적하는 것이 도움이 될 것이라고 생각합니다. 나는이 혼동의 예로써 위의 인용문에서 두 단어를 강조했다. 은 SQL Server 설명서는 유니 코드와 비 유니 코드로 말할 때 데이터 , 그들은되어 있지 에 대해 이야기 문자 . 그들은 특정 문자를 나타내는 바이트 시퀀스를 말하고 있습니다. 유니 유형 (주요 차이점 NCHAR, NVARCHAR, XML및 중단 / 악 NTEXT)과 유니 코드 유형 ( CHAR, VARCHAR및 중단 / 악 TEXT) 무슨 종류의 바이트 시퀀스들은 저장할 수있다.

비 유니 코드 유형은 여러 8 비트 인코딩 중 하나를 저장하는 반면 유니 코드 유형은 단일 16 비트 유니 코드 인코딩 인 UTF-16 Little Endian을 저장합니다. 다른 답변에서 언급했듯이 8 비트 / 비 유니 코드 인코딩으로 저장할 수있는 문자는 데이터 정렬에 의해 결정되는 코드 페이지에 따라 다릅니다. 다른 사람들은 "문자"의 바이트 값이 발견 된 코드 페이지마다 다를 수 있다고 언급했지만 바이트 값은 여러 EBCDIC 코드 페이지 중 하나를 처리 할 때 동일한 코드 페이지 내에서도 달라질 수 있습니다 (Windows- 이전 버전에서만 발견 된 1252)는 실제로 사용되는 SQL Server 데이터 정렬 (예 : 이름이로 시작하는 SQL Server 데이터 정렬)을 사용해서는 안됩니다 SQL_.

따라서 정의는 정확합니다. 유니 코드가 아닌 유형으로 저장할 수있는 문자는 항상 8 비트입니다 (두 개의 8 비트 값을 단일 "문자"로 조합하여 사용하는 경우에도 Double- 바이트 문자 세트 / DBCS 코드 페이지에서 허용). 그리고 유니 코드 데이터 유형은 두 개의 16 비트 값을 단일 "문자"(즉, 보조 문자를 나타내는 대리 쌍)로 조합하여 사용하더라도 항상 16 비트입니다.

그리고 SQL Server 가 SQL Server 2019부터 UTF-8 인코딩 VARCHARCHAR데이터 유형을 기본적으로 지원하기 때문에

VARCHAR더 이상 "비 유니 코드"라고 할 수 없습니다. 따라서 2018 년 9 월 SQL Server 2019의 첫 번째 공개 베타부터 SQL Server 2019 VARCHAR이전 버전으로 말할 때도 "8 비트 데이터 유형"이라고합니다.이 용어는 4 가지 유형 모두에 해당됩니다. 함께 사용할 수있는 인코딩 VARCHAR:

  1. 확장 ASCII
  2. 더블 바이트 문자 집합 (DBCS)
  3. EBCDIC
  4. UTF-8 (유니 코드)

TEXTSQL Server 2005에서 더 이상 사용되지 않으므로 사용하지 않는 데이터 형식 만 "비 유니 코드"이지만 기술 일 뿐이므로 "8 비트 데이터 형식"이라고하는 것이 정확합니다.

NVARCHAR, NCHARNTEXT"UTF-16"또는 "16 비트 데이터 형식"으로 지칭 될 수있다. 오라클은에 대해 "유니 코드 전용"이라는 용어를 사용 NVARCHAR하지만 UTF-8 (유니 코드 인코딩)을 사용할 가능성을 분명히 배제하지는 않습니다. 처음 두 옵션.

새로운 UTF-8 인코딩에 대한 자세한 내용은 다음 게시물을 참조하십시오.

SQL Server 2019의 기본 UTF-8 지원 : 구주 또는 거짓 예언자?

추신 : 나는 이러한 변화를 반영하기 위해 SQL Server 설명서를 업데이트하면서 천천히 노력하고 있습니다.

PPS Microsoft는 문제에서 참조 된 char 및 varchar 설명서를 포함하여 UTF-8 정보로 일부 페이지를 이미 업데이트했습니다 . 더 이상 "비 유니 코드"라는 문구가 포함되어 있지 않습니다. 그러나 그것은 단지 참고 일뿐입니다. 이것은 유니 코드 전용으로 잘못 간주 된 문자가 포함 된 비 유니 코드 인코딩에 관한 것이므로 질문을 변경하지 않습니다.


3

이 질문에는 유니 코드가 무엇인지에 대한 중심적인 오해가 포함되어 있습니다. UTF-8 및 UTF-16과 같은 인코딩과 함께 유니 코드 문자 집합은 컴퓨터에서 텍스트를 나타내는 여러 가지 방법 중 하나이며 다른 모든 문자 집합과 인코딩을 대체하는 것이 목표입니다. "유니 코드가 아닌 데이터"가 "유니 코드로 존재하지 않는 문자"를 의미하는 경우,이 답변에 사용한 텍스트는 라틴 알파벳의 모든 문자와 일상 영어에서 사용되는 일반적인 문장 부호가 없기 때문에 해당 유형으로 저장할 수 없습니다. 유니 코드에 포함되어 있습니다.

텍스트 표현은 크게 두 부분으로 생각할 수 있습니다 . 서로 다른 문자 (문자, 숫자, 기호 등)를 참조 차트의 숫자에 매핑 하는 문자 집합 ; 및 이들 숫자를 비트 패턴 (디스크, 네트워크 연결 등)으로 나타내는 인코딩 . 여기서 우리는 대부분 첫 번째 부분에 관심이 있습니다. 특정 문자 집합에 대한 차트에 어떤 문자가 나열되어 있습니까?

유니 코드는 세계의 모든 문자에 대해 숫자 ( "코드 포인트"라고 함)를 갖는 것을 목표로하기 때문에 Wikipedia와 같은 참조는 종종 문자의 유니 코드 위치를 표준 참조 정보로 참조합니다. 그러나 이것이 다른 문자 집합에도 동일한 문자에 대한 매핑이 없음을 의미하지는 않습니다.

여전히 가장 오래되고 간단한 문자 세트 (및 인코딩) 중 하나는 ASCII이며, 각 문자를 인코딩하는 데 7 비트를 사용하므로 128 개의 서로 다른 문자 (0-127)에 대한 매핑이 있습니다. 여기에는 많은 악센트 부호가있는 문자와 공통 기호가 제외되므로 이후 인코딩은 8 비트를 사용하고 동일한 첫 128자를 매핑하여 위치를 128에서 255까지 채워 문자 세트에 추가합니다. 표준 ISO 8859-1ISO 8859- 15 및 Microsoft 관련 Windows 코드 페이지 1252 .

에 저장 등의 "유니 코드 문자열": 그래서, MS SQL Server에 다시 와서 nchar, nvarchar또는 ntext나타낼 수, 열을 모두 는 데이터를 저장하는 코딩하는 유니 코드를 사용하기 때문에, 유니 코드 문자 집합에 매핑 된 문자를. A "비 유니 코드 문자열이"로 저장 char, varchar또는 text컬럼에 매핑 된 문자 만 나타낼 수있는 다른 인코딩을 . 비 유니 코드 열에 저장할 수있는 것은 유니 코드 열에도 저장할 수 있지만 그 반대의 경우도 마찬가지입니다.

저장할 수있는 문자를 정확히 알려 면이 Microsoft 참조 페이지에 설명 된 대로 Microsoft가 "코드 페이지"라고하는 것을 나타내는 "콜 레이션"을 알아야합니다 . 앞에서 언급 한 매우 일반적인 코드 페이지 1252를 사용하고있을 가능성이 큽니다.

언급 한 문자는 유니 코드 및 코드 페이지 1252 모두에 존재합니다.

  • 상표 (™)는 위치 8482에서 유니 코드로, 위치 153에서 CP1252로 나타납니다.
  • 등록 된 (®)은 174 위치에서 유니 코드와 CP1252로 나타납니다.

3
“유니 코드는 컴퓨터에서 사용하기 위해 텍스트를 인코딩하는 여러 가지 방법 중 하나입니다.” – 맞지 않습니다. 유니 코드는 문자와 기호의 모음 일뿐입니다. 각 문자에는 고유 한 코드 포인트 가 있으며 숫자입니다. 그런 다음 인코딩 작업은 해당 코드 포인트를 바이트 시퀀스와 일치시키는 것입니다. UTF-8 및 UTF-16은 인코딩이며 유니 코드는 인코딩되지 않습니다.
poke

@poke 대답에서 계속해서 말하지만, 여기서는 "인코딩"을 사용하여 "문자를 차트의 위치로 매핑"과 "이 위치를 비트 시퀀스로 표현"을 나타냅니다. 사용하기에 더 좋은 용어가 있을지 모르지만 그 용어가 무엇인지 잘 모르겠습니다.
IMSoP

3
글쎄, 당신은 당신의 자신의 정의와 함께 "인코딩"을 사용할 수 없습니다. 여기서 nitpicking하는 것은 유감 스럽지만 "질문에는 유니 코드가 무엇인지에 대한 중심적인 오해가 있습니다" 라는 답변에서 그렇게 할 수 없습니다 .
poke

2
IMSoP (및 @poke) : IMSOP의 딜레마에도 동조 적이지만, 인코딩 이외의 다른 의미로 "인코딩"을 사용하는 것에 대한 이해에 전적으로 동의합니다. 선호하는 것은 다중 인코딩을 갖는 문자 집합으로 유니 코드를 참조하는 반면, 일반적으로 문자 집합과 인코딩은 대부분의 (일부 또는 전부?) 일대일 관계로 인해 상호 교환 가능하게 사용됩니다.
Solomon Rutzky

2
좋은 대답입니다. 나는 절대적으로 모든 소프트웨어 개발자에게 절대적으로 긍정적으로 알아야 할 유니 코드 및 문자 세트 에 대한 링크를 추가하는 것이 좋습니다 .
jpmc26
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.