Unicode文字列変数を、Unicodeコードポイントに基づいて特定の文字に設定したい。
65535を超えるコードポイントを使用したいのですが、SQL Server 2008 R2データベースの照合順序はSQL_Latin1_General_CP1_CI_AS
です。
MicrosoftのNCHARドキュメント によると、NCHAR
関数は次のように整数を取ります。
integer_expression
データベースの照合に補助文字(SC)フラグが含まれていない場合、これは0〜65535(0〜0xFFFF)の正の整数です。この範囲外の値が指定された場合、NULLが返されます。補助文字の詳細については、照合およびUnicodeサポートを参照してください。
データベースの照合が補助文字(SC)フラグをサポートしている場合、これは0〜1114111(0〜0x10FFFF)の正の整数です。この範囲外の値が指定された場合、NULLが返されます。
したがって、このコード:
SELECT NCHAR(128512);
このデータベースでNULL
を返します。
私はこれと同じように返すことを望みます:
SELECT N'????';
照合順序に「補助文字(SC)フラグが含まれていない」データベースで、コードを使用して(実際の絵文字を使用せずに)Unicode文字列変数(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
の観点以外で拡張文字を理解して処理できる理由についての説明はありますか?
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およびUTF-16の設計には十分な先見性があり、UCS-2マッピングはUTF-16マッピングの完全なサブセットです(つまり、0-65535/0x0000-0xFFFFの範囲)。 UTF-16のis UCS-2)。さらに、UTF-16の65536-1114111(0x10000-0x10FFFF)の範囲は、この目的のために予約されていて、それ以外にはない意味。この2つのコードポイントの組み合わせはサロゲートペアと呼ばれ、サロゲートペアはUCS-2の範囲を超える文字を表し、補助文字と呼ばれます。
これらすべての情報は、SQL ServerのNVARCHAR
/Unicodeデータの2つの側面を説明しています。
NCHAR()
だけでなく)は、補助文字対応照合(SCA、つまり_SC
、または_140_
を備えた照合を使用しない場合、サロゲートペア/補助文字を処理しませんただし、名前に_BIN*
は含まれません)。非SCA照合(特にSQL_
照合)は、UTF-16が完了する前に最初に実装されたためです(2000年のいつかと思います)。名前にSQL_
または_90_
を含むが_100_
を含まない非_SC
照合順序は、比較と並べ替えの点で補助文字を最小限にサポートします。NVARCHAR
/NCHAR
/XML
/NTEXT
データ型に格納できます。 -2とUTF-16はまったく同じバイトシーケンスです。唯一の違いは、UTF-16がサロゲートペアを構築するためにサロゲートコードポイントを使用し、UCS-2はそれらを任意の文字にマップできないため、組み込み関数では2つの不明な文字として表示されることです。その背景情報を念頭に置いて、具体的な質問に進むことができます。
SELECT NCHAR(128512);
がこれと同じを返すようにしたい:SELECT N'????';
これは、クエリが実行されている現在のデータベースに、補助文字対応の既定の照合順序があり、SQL Server 2012で導入された場合にのみ発生します。文字列入力パラメーターを持つ組み込み関数は、照合順序を指定できますCOLLATE
句(つまりLEN(N'string' COLLATE Some_Collation_SC)
)を介してインライン化し、SCAのデフォルトの照合順序を持つデータベース内で実行する必要はありませんneed。ただし、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照合順序(つまり、SQL_
で始まるもの)は、Windows照合順序(SQL_
で始まっていないもの)のために廃止されました。したがって、SQL_
照合順序は更新されないため、_SC
オプションを含む新しいバージョンはありません(SQL Server 2017以降、 すべての新しい照合順序は、補助文字 を自動的にサポートし、必要ありません。または、_SC
フラグがあり、はい、すぐ上に表示されているクエリは、SQL Server 2019で追加された_UTF8
照合を選択するだけでなく、それを考慮しています。
古いインスタンスに照合順序をインストールできますか?
いいえ、以前のバージョンのSQL Serverに照合順序をインストールすることはできません。
照合順序に「補助文字(SC)フラグが含まれていない」データベースで、コードを使用して(実際の補助文字を使用せずに)Unicode文字列変数(nvarcharなど)を補助文字に設定するにはどうすればよいですか?
...
サーバーはSQL Server 2008 R2ですが、それ以降のバージョンの解決策にも興味があります。
SCA照合を使用しない場合、次の2つの方法で65535/U + FFFFを超えるコードポイントを挿入できます。
NCHAR()
関数の2つの呼び出しでサロゲートペアを指定します。VARBINARY
形式を変換するという観点からサロゲートペアを指定します。補助文字/サロゲートペアを挿入するこれらの2つの方法は、有効な照合順序が補助文字に対応している場合でも機能し、少なくとも2005年までのSQL Serverのすべてのバージョンでまったく同じように機能するはずです(ただし、おそらくSQL Server 2000も)。
例:
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
の両方の形式)を取得できます。また、入力パラメーターのタイプは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 ????
更新2:より良い更新!
上記のiTVFを適合させて、188,657コードポイントを返すようにしたので、特定の値に合わせる必要はありません。もちろん、TVFの場合、WHERE
句を追加して、特定のコードポイント、コードポイントの範囲、または「類似文字」などでフィルタリングできます。また、事前フォーマット済みの追加の列が含まれていますT-SQLで各コードポイント(BMPと補足文字の両方))を構築するエスケープシーケンス(「_SC
」または「_140_
」照合を必要としない)、HTML(およびXML)、一般的なスタイル多くのアプリ言語( "\ uHHHH"; C++/C#/ F#/ Java/JavaScript/Julia /など)に使用されます)、そして最後に、すべてのコードポイントを処理する少し新しい他の一般的なスタイルBMP( "\ UHHHHHHHH"; C/C++/C#/ F#/ Julia /などに使用されます)だけではありません。
それについてここですべて読んでください: