SQL Server Unicode / NVARCHAR文字列を絵文字または補助文字に設定するにはどうすればよいですか?


22

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など)を絵文字に設定するにはどうすればよいですか?

絵文字Unicodeコードポイントの全リスト

(最終的には、すべてのキャラクターが機能するようにします。参照しやすいように絵文字を選択しました。)

(サーバーは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
問題ない。私はあなたがまだされていなかったと指摘必要とするだけで、あなたに感謝かもしれない/ ...適応を利用することができ、何かを
ソロモンRutzky

回答:


35

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つの側面を説明しています。

  1. いくつかの組み込み関数(だけでなくNCHAR())は、補助文字認識照合(SCA、つまり、名前に含まれる_SCまたは 名前では_140_ない_BIN*もの)を使用していない場合、サロゲートペア/補足文字を処理しません。SQL_照合順序)は、UTF-16が完了する前に最初に実装されました(2000年のどこかで、私は信じています)。名前があるか、名前に含まれているが、比較と並べ替えの観点から補助文字を最小限サポートしていない非SQL_照合。_90__100__SC
  2. 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 Collat​​ions(つまり、で始まるものSQL_)は、Windows Collat​​ions(で始まるものではない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を超えるコードポイントを挿入できます。

  1. サロゲートペアを、NCHAR()関数の2つの呼び出しで指定します。それぞれの呼び出しには、ペアの1つの部分が含まれます。
  2. サロゲートペア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)の任意のコードポイントからサロゲートペアの値(両方INTBINARY形式)を取得できます。また、入力パラメーターが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文字に簡単にアクセス/研究する(はい、絵文字を含む😸)


1
素晴らしい仕事ソロモン!素晴らしい説明
ローネン・アリエリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.