SQL Server 유니 코드 / NVARCHAR 문자열을 이모티콘 또는 보충 문자로 설정하려면 어떻게합니까?


23

유니 코드 코드 변수를 기반으로 유니 코드 문자열 변수를 특정 문자로 설정하고 싶습니다.

65535 이상의 코드 포인트를 사용하고 싶지만 SQL Server 2008 R2 데이터베이스의 데이터 정렬은 SQL_Latin1_General_CP1_CI_AS입니다.

에 따르면 마이크로 소프트의 NCHAR 문서NCHAR다음과 같이 함수는 정수를 취합니다

정수식

데이터베이스의 데이터 정렬에 보충 문자 (SC) 플래그가 포함되어 있지 않은 경우, 이는 0-65535 (0-0xFFFF)의 양의 정수입니다. 이 범위를 벗어난 값을 지정하면 NULL이 반환됩니다. 보충 문자에 대한 자세한 내용은 데이터 정렬 및 유니 코드 지원을 참조하십시오.

데이터베이스의 데이터 정렬이 보충 문자 (SC) 플래그를 지원할 때, 이는 0-1114111 (0-0x10FFFF)의 양의 정수입니다. 이 범위를 벗어난 값을 지정하면 NULL이 반환됩니다.

따라서이 코드 :

SELECT NCHAR(128512);

NULL이 데이터베이스에서 반환 합니다.

다음과 같이 반환하고 싶습니다.

SELECT N'😀';

데이터 정렬이 "보충 문자 (SC) 플래그를 포함하지 않는"데이터베이스에서 코드를 사용하여 (실제 이모티콘 문자를 사용하지 않고) 유니 코드 문자열 변수 (예 : nvarchar)를 이모티콘으로 설정하려면 어떻게해야합니까?

이모티콘 유니 코드 코드 포인트의 전체 목록

(궁극적으로 나는 어떤 캐릭터라도 작동하기를 원합니다. 참조하기 쉽도록 이모티콘을 선택했습니다.)

(서버는 SQL Server 2008 R2이지만 최신 버전의 솔루션에 대해서도 궁금합니다.)

방법이 없다고 가정하면 적절한 데이터 정렬이있는 다른 데이터베이스에서 인라인 사용자 정의 함수를 참조 할 수 있습니까?

"보조 문자"플래그가있는 데이터 정렬을 찾으려면 어떻게합니까?

이것은 우리 서버에 대한 레코드를 반환하지 않습니다 :

SELECT * FROM sys.fn_helpcollations() 
WHERE name LIKE 'SQL%[_]SC';

SQL Server 2012가 도입 Latin1_General_100_CI_AS_SC된 것처럼 보입니다 . 이전 인스턴스에 데이터 정렬을 설치할 수 있습니까?

데이터 정렬 참조 :

데이터 정렬에 관계없이 SQL Server가 관점을 제외하고 확장 문자를 이해하고 처리 할 수있는 이유에 대한 설명이 NCHAR있습니까?


종합적인 추가 정보에 감사드립니다. 더 이상이 문제에 직면하지 않지만이 정보를 정신적으로 북마크에 추가합니다.
라일리 메이저

1
문제 없어. 나는 당신이 여전히 무언가를 필요로 한다고 생각하지 않았습니다 . 단지 당신이 적응을 이용할 수 있다는 것을 감사하게 생각할 수있을 것입니다 ...
Solomon Rutzky

답변:


36

UCS-2 인코딩은 문자 당 항상 2 바이트이며 범위는 0-65535 (0x0000-0xFFFF)입니다. UTF-16 (Big Endian 또는 Little Endian에 관계없이)의 범위는 0-1114111 (0x0000-0x10FFFF)입니다. UTF-16의 0-65535 / 0x0000-0xFFFF 범위는 문자 당 2 바이트 인 반면 65536 / 0xFFFF 이상의 범위는 문자 당 4 바이트입니다.

Windows와 SQL Server는 UCS-2 인코딩을 사용할 수 있었고 UTF-16이 아직 마무리되지 않았기 때문에 시작했습니다. 그러나 UCS-2와 UTF-16의 디자인에는 UCS-2 매핑이 UTF-16 매핑의 완전한 하위 집합이라는 의미가 충분히 있습니다 (즉, 0-65535 / 0x0000-0xFFFF 범위). UTF-16 UCS-2입니다). UTF-16의 65536-1114111 (0x10000-0x10FFFF) 범위는 UCS-2 범위의 두 코드 포인트 (범위 0xD800 – 0xDBFF 및 0xDC00 – 0xDFFF 범위)로 구성되며, 그렇지 않은 경우에는 의미. 이 두 코드 포인트의 조합을 대리 쌍이라고하며 대리 쌍은 보충 문자로 알려진 UCS-2 범위를 벗어난 문자를 나타냅니다.

이 모든 정보는 NVARCHARSQL Server에서 / 유니 코드 데이터 의 두 가지 측면을 설명합니다 .

  1. 여러 내장 함수 (다만 NCHAR()보충 문자 인식 데이터 정렬 사용하지 않을 경우 대리 쌍 / 보조 문자를 처리하지 않는) (SCA를, 즉 하나 _SC, 또는 _140_ 하지만 _BIN*이름에서) 때문에 비 SCA 데이터 정렬 (특히 SQL_데이터 정렬)은 원래 UTF-16이 완료되기 전에 구현되었습니다 (때로는 2000 년에 믿습니다). 이름 SQL__90_있거나 _100_이름은 있지만 _SC비교 및 정렬 측면에서 보충 문자를 최소한으로 지원 하지 않는 비 콜 레이션 .
  2. 전체 유니 코드 / UTF-16 문자 세트로는, 데이터 손실없이 저장 될 수있는 NVARCHAR/ NCHAR/ XML/ NTEXT데이터 유형 UCS-2 및 UTF-16이 동일한 바이트 시퀀스이기 때문에. 유일한 차이점은 UTF-16은 서로 게이트 코드 포인트를 사용하여 서로 게이트 쌍을 구성한다는 점입니다. UCS-2는 단순히 문자를 매핑 할 수 없으므로 내장 함수에 두 개의 알 수없는 문자로 표시됩니다.

이러한 배경 정보를 염두에두고 이제 다음과 같은 구체적인 질문을 수행 할 수 있습니다.

SELECT NCHAR(128512);다음과 같이 반환하고 싶습니다 .SELECT N'😀';

쿼리가 실행되는 현재 데이터베이스에 보조 문자 인식 보조 기본 인식 데이터 정렬이 있고 SQL Server 2012에 도입 된 기본 데이터 정렬이있는 경우에만 발생할 수 있습니다. 문자열 입력 매개 변수가있는 기본 제공 함수는 데이터 정렬을 제공 할 수 있습니다. COLLATE절 (예 :)을 통해 인라인 하고 SCA 기본 데이터 정렬이있는 데이터베이스 내에서 실행될 필요LEN(N'string' COLLATE Some_Collation_SC) 가 없습니다 . 그러나 입력 매개 변수 를 받아들이고 해당 절 에서 절이 유효하지 않은 내장 함수 ( 현재 데이터베이스에 보조 문자 인식 보조 기본 정렬이있는 경우 보조 문자 만 지원 하는 이유 는 필요하지 않습니다) 불편을 끼쳐 드려 죄송합니다. 제 의견에 투표 해주세요.NCHAR()INTCOLLATENCHAR()NCHAR () 함수는 활성 데이터베이스의 기본 데이터 정렬에 관계없이 항상 0x10000-0x10FFFF 값에 대해 보충 문자를 반환해야합니다 .)

데이터 정렬에 관계없이 SQL Server가 관점을 제외하고 확장 문자를 이해하고 처리 할 수있는 이유에 대한 설명이 NCHAR있습니까?

SQL Server가 데이터 손실없이 보충 문자를 저장하고 검색하는 방법은이 답변의 맨 위 섹션에 설명되어 있습니다. 그러나 NCHAR보조 문자 (SCA 데이터 정렬을 사용하지 않는 경우)에 문제가있는 유일한 내장 기능인 것은 사실이 아닙니다. 예를 들어, LEN(N'😀' COLLATE SQL_Latin1_General_CP1_CI_AS)값 2를 LEN(N'😀' COLLATE Latin1_General_100_CI_AS_SC)반환하고 값 1 을 반환합니다.

질문에 게시 된 두 번째 링크 (예 : "Microsoft 보조 문자 데이터 정렬 정보")로 이동 한 다음 조금 아래로 스크롤하면 기본 제공 함수 차트와 해당 함수가 효과적인 데이터 정렬을 기반으로 동작하는 방식을 볼 수 있습니다.

"보조 문자"플래그가있는 데이터 정렬을 찾으려면 어떻게합니까?

2012 년 이전의 SQL Server 버전에서는 할 수 없습니다. 그러나 SQL Server 2012부터 다음 쿼리를 사용할 수 있습니다.

SELECT col.*
FROM   sys.fn_helpcollations() col
WHERE  col.[name] LIKE N'%[_]SC'
OR     col.[name] LIKE N'%[_]SC[_]%'
OR     (COLLATIONPROPERTY(col.[name], 'Version') = 3
      AND col.[name] NOT LIKE N'%[_]BIN%');

쿼리가 닫혔지만 패턴이 시작 SQL되고 SQL Server 데이터 정렬 (으로 시작하는 데이터 정렬 SQL_)은 Windows 데이터 정렬 (으로 시작하지 않는)을 위해 한동안 사용되지 않습니다 SQL_. 따라서 SQL_데이터 정렬이 업데이트되지 않으므로 _SC옵션을 포함하는 최신 버전이 없습니다 (SQL Server 2017부터는 모든 새 데이터 정렬이 자동으로 보조 문자를 지원 하며 _SC플래그 가 필요하거나 없습니다) . 바로 위에 표시된 _UTF8것은 SQL Server 2019에 추가 된 데이터 정렬 을 선택하는 것 입니다.

이전 인스턴스에 데이터 정렬을 설치할 수 있습니까?

아니요, 이전 버전의 SQL Server에는 데이터 정렬을 설치할 수 없습니다.

데이터 정렬이 "보충 문자 (SC) 플래그를 포함하지 않는"데이터베이스에서 코드 (실제 보충 문자를 사용하지 않고)를 사용하여 유니 코드 문자열 변수 (예 : nvarchar)를 보충 문자로 설정하려면 어떻게해야합니까?
...
서버는 SQL Server 2008 R2이지만 이후 버전의 솔루션에 대해서도 궁금합니다.

SCA 데이터 정렬을 사용하지 않는 경우 다음 두 가지 방법으로 65535 / U + FFFF 이상의 코드 포인트를 삽입 할 수 있습니다.

  1. NCHAR()함수 에 대한 두 번의 호출로 각각 쌍의 한 부분으로 대리 쌍을 지정하십시오.
  2. VARBINARY리틀 엔디안 (즉, 역) 바이트 시퀀스 의 형식 을 변환하는 관점에서 대리 쌍을 지정하십시오 .

보충 문자 / 서로 게이트 쌍을 삽입하는이 두 가지 방법은 효과적인 데이터 정렬이 보충 문자 인식 인 경우에도 작동하며 적어도 2005 년까지 모든 SQL Server 버전에서 동일하게 작동해야합니다. SQL Server 2000).

예:

  • 캐릭터:

                       💩

  • 이름 :                똥 더미
  • 10 진수 :            128169
  • 코드 포인트 :       U + 1F4A9
  • 대리 쌍 : U + D83D 및 U + DF21
SELECT N'💩', -- 💩
       UNICODE(N'💩' COLLATE Latin1_General_100_CI_AS), -- 55357
       UNICODE(N'💩' COLLATE Latin1_General_100_CI_AS_SC), -- 128169
       NCHAR(128169), -- 💩 in DB with _SC Collation, else NULL
       NCHAR(0x1F4A9), -- 💩 in DB with _SC Collation, else NULL
       CONVERT(VARBINARY(4), 128169), -- 0x0001F4A9
       CONVERT(VARBINARY(4), N'💩'), -- 0x3DD8A9DC
       CONVERT(NVARCHAR(10), 0x3DD8A9DC), -- 💩 (regardless of DB Collation)
       NCHAR(0xD83D) + NCHAR(0xDCA9) -- 💩 (regardless of DB Collation)

최신 정보

다음 iTVF를 사용하여 65536-1114111 (0x010000-0x10FFFF) 사이의 코드 포인트에서 Surrogate Pair 값 ( 양식 INTBINARY형식) 을 얻을 수 있습니다 . 또한 입력 매개 변수가 유형 인 동안 INT코드 포인트의 2 진 / 16 진 형식을 전달하면 암시 적으로 올바른 정수 값으로 변환됩니다.

CREATE FUNCTION dbo.GetSupplementaryCharacterInfo(@CodePoint INT)
RETURNS TABLE
WITH SCHEMABINDING
AS RETURN

WITH calc AS
(
  SELECT 55232 + (@CodePoint / 1024) AS [HighSurrogateINT],
         56320 + (@CodePoint % 1024) AS [LowSurrogateINT]
  WHERE  @CodePoint BETWEEN  65536 AND 1114111
)
SELECT @CodePoint AS [CodePointINT],
       HighSurrogateINT,
       LowSurrogateINT,
       CONVERT(VARBINARY(3), @CodePoint) AS [CodePointBIN],
       CONVERT(BINARY(2), HighSurrogateINT) AS [HighSurrogateBIN],
       CONVERT(BINARY(2), LowSurrogateINT) AS [LowSurrogateBIN],
       CONVERT(binary(4), NCHAR(HighSurrogateINT) + NCHAR(LowSurrogateINT)) AS [UTF-16LE],
       NCHAR(HighSurrogateINT) + NCHAR(LowSurrogateINT) AS [Character]
FROM   calc;
GO

위의 함수를 사용하여 다음 두 쿼리가 있습니다.

SELECT * FROM dbo.GetSupplementaryCharacterInfo(128169);

SELECT * FROM dbo.GetSupplementaryCharacterInfo(0x01F4A9);

둘 다 다음을 반환합니다.

CodePoint  HighSurrogate  LowSurrgate  CodePoint  HighSurrgate  LowSurrgate  UTF-16LE   Char
INT        INT            INT          BIN        BIN           BIN                     actr
128169     55357          56489        0x01F4A9   0xD83D        0xDCA9       0x3DD8A9DC   💩

업데이트 2 : 더 나은 업데이트!

위에 표시된 iTVF를 조정하여 이제 188,657 개의 코드 포인트를 반환하므로 특정 값에 맞출 필요가 없습니다. 물론 TVF 인 WHERE경우 특정 코드 포인트 또는 코드 포인트 범위 또는 "유사 문자"등을 필터링 하는 절을 추가 할 수 있습니다 . 또한 각 코드를 구성하기 위해 사전 형식화 된 이스케이프 시퀀스가있는 추가 열이 포함됩니다. 포인트 T-SQL, HTML에서 (모두 BMP 및 보조 캐릭터), 그리고 C 스타일 (예 \xHHHH). 여기에 대한 모든 내용을 읽으십시오.

SSMS Tip # 3 : 모든 유니 코드 문자를 쉽게 액세스 / 연구 (예, 이모티콘 포함)


1
대단한 일 솔로몬! 멋진 설명
Ronen Ariely
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.