UCS-2エンコーディングは常に文字ごとに2バイトで、範囲は0〜65535(0x0000-0xFFFF)です。UTF-16(ビッグエンディアンまたはリトルエンディアンに関係なく)の範囲は0〜1114111(0x0000〜0x10FFFF)です。UTF-16の0-65535 / 0x0000-0xFFFFの範囲は1文字あたり2バイトですが、65536 / 0xFFFFを超える範囲は1文字あたり4バイトです。
WindowsとSQL Serverは、UCS-2エンコーディングが使用可能であり、UTF-16がまだ確定していないため、UCS-2エンコーディングの使用を開始しました。ただし、幸いなことに、UCS-2およびUTF-16の設計には、UCS-2マッピングがUTF-16マッピングの完全なサブセット(つまり、0〜65535 / 0x0000-0xFFFFの範囲) UTF-16 は UCS-2です)。および、UTF-16の65536-1114111(0x10000-0x10FFFF)の範囲は、UCS-2範囲の2つのコードポイント(具体的には0xD800 – 0xDBFFおよび0xDC00 – 0xDFFFの範囲)から構築され、この目的のために予約されています。意味。この2つのコードポイントの組み合わせは、サロゲートペアと呼ばれ、サロゲートペアは、補助文字と呼ばれるUCS-2範囲を超える文字を表します。
その情報はすべてNVARCHAR
、SQL ServerのUnicodeデータの2つの側面を説明しています。
- いくつかの組み込み関数(だけでなく
NCHAR()
)は、補助文字認識照合(SCA、つまり、名前に含まれる_SC
、または 名前では_140_
ない_BIN*
もの)を使用していない場合、サロゲートペア/補足文字を処理しません。SQL_
照合順序)は、UTF-16が完了する前に最初に実装されました(2000年のどこかで、私は信じています)。名前があるか、名前に含まれているが、比較と並べ替えの観点から補助文字を最小限サポートしていない非SQL_
照合。_90_
_100_
_SC
- UCS-2とUTF-16はまったく同じバイトシーケンスであるため、完全なUnicode / UTF-16文字セットをデータ損失なしで
NVARCHAR
/ NCHAR
/ XML
/ NTEXT
データ型に格納できます。唯一の違いは、UTF-16はサロゲートコードポイントを使用してサロゲートペアを構築することです。UCS-2はサロゲートペアを単に任意の文字にマッピングできないため、組み込み関数からは2つの未知の文字として表示されます。
その背景情報を念頭に置いて、特定の質問に答えることができます。
私はSELECT NCHAR(128512);
これと同じを返したいです:SELECT N'😀';
これは、クエリが実行されている現在のデータベースに補助文字対応の既定の照合があり、それらがSQL Server 2012で導入された場合にのみ発生します。文字列入力パラメーターを持つ組み込み関数は照合を提供できますCOLLATE
句を介してインライン(つまりLEN(N'string' COLLATE Some_Collation_SC)
)であり、SCAデフォルト照合を持つデータベース内で実行する必要はありません。ただし、入力パラメーターをNCHAR()
受け入れるなどの組み込み関数INT
やそのCOLLATE
句はそのコンテキストでは無効です(そのためNCHAR()
、現在のデータベースに補助文字対応の既定の照合がある場合にのみ補助文字がサポートされますが、これは不要です)変更される可能性があるため、私の提案に投票してください: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 を返します。
質問に投稿された2番目のリンク(「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 Collations(つまり、で始まるものSQL_
)は、Windows Collations(で始まるものではないSQL_
)を支持してしばらくの間廃止されました。そのため、SQL_
照合順序は更新されていないため、_SC
オプションを含む新しいバージョンはありません(SQL Server 2017以降、すべての新しい照合順序は自動的に補助文字をサポートし、_SC
フラグを必要としないか、持っていません;はい、クエリそのすぐ上のアカウントと_UTF8
、SQL Server 2019で追加された照合の選択を示しています)。
古いインスタンスに照合をインストールできますか?
いいえ、照合順序を以前のバージョンのSQL Serverにインストールすることはできません。
照合に「補助文字(SC)フラグが含まれていない」データベースで、コードを使用して(実際の補助文字を使用せずに)Unicode文字列変数(nvarcharなど)を補助文字に設定するにはどうすればよいですか?
...
サーバーはSQL Server 2008 R2ですが、今後のバージョンのソリューションについても興味があります。
SCA照合を使用しない場合、次の2つの方法で65535 / U + FFFFを超えるコードポイントを挿入できます。
- サロゲートペアを、
NCHAR()
関数の2つの呼び出しで指定します。それぞれの呼び出しには、ペアの1つの部分が含まれます。
- サロゲートペア
VARBINARY
を、リトルエンディアン(つまり逆)バイトシーケンスの形式の変換に関して指定します。
補助文字/サロゲートペアを挿入するこれら2つの方法は、有効な照合が補助文字対応であっても機能し、少なくとも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)の任意のコードポイントからサロゲートペアの値(両方INT
とBINARY
形式)を取得できます。また、入力パラメーターがtypeのINT
場合、コードポイントのバイナリ/ 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
、次の2つのクエリを上記の関数を使用します:
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 💩
UPDATE 2:アンさらに良い更新!
上記のiTVFが188,657コードポイントを返すように調整したので、特定の値に合わせる必要はありません。もちろん、TVFであるWHERE
ため、特定のコードポイント、コードポイントの範囲、または「類似文字」などでフィルタリングする句を追加できます。また、各コードを構築するための事前フォーマットされたエスケープシーケンスを持つ追加の列が含まれますT-SQL、HTML、およびCスタイル(つまり\xHHHH
)のポイント(BMPと補助文字の両方)。ここですべてを読んでください:
SSMSヒント#3:すべてのUnicode文字に簡単にアクセス/研究する(はい、絵文字を含む😸)