SQLCLR を使用してカスタムのユーザー定義型を作成することはできません 、いずれにせよ、ネイティブタイプの代替品を手に入れようとしています。特殊なデータを扱うものを作成するのに非常に便利です。しかし、異なるエンコーディングの文字列であっても、特殊化されたものとはほど遠いものです。文字列データにこのルートを使用すると、システムの使いやすさが損なわれます。パフォーマンスは言うまでもなく、any を使用できないためです。 組み込みの文字列関数。
ディスク容量を節約できたとしても、全体的なパフォーマンスで失われるものによって、それらの利点は失われます。 UDT の格納は、VARBINARY
にシリアル化することによって行われます。 . 何かを行うために 「バイナリ」/「序数」比較以外の文字列比較または並べ替えでは、他のすべての値を 1 つずつ UTF-8 に変換してから、言語の違いを説明できる文字列比較を行う必要があります。そして、その変換は UDT 内で行う必要があります。つまり、XML データ型と同様に、UDT を作成して特定の値を保持し、その UDT のメソッドを公開して文字列パラメーターを受け入れて比較を行います (つまり、Utf8String.Compare(alias.field1)
または、型の演算子を定義する場合、Utf8string1 = Utf8string2
=
を持つ 演算子は UTF-8 エンコーディングで文字列を取得し、CompareInfo.Compare()
を実行します ).
上記の考慮事項に加えて、特に NVARCHAR(MAX)
を使用する場合は、SQLCLR API を介して値をやり取りするとコストがかかることも考慮する必要があります。 または VARBINARY(MAX)
NVARCHAR(1 - 4000)
とは対照的に および VARBINARY(1 - 4000)
それぞれ (この区別を、SqlChars
の使用を意味するものと混同しないでください) / SqlBytes
vs SqlString
/ SqlBinary
).
最後に (少なくとも UDT の使用に関して)、お問い合わせの UDT がサンプル コードであるという事実を見逃さないでください。 .言及されている唯一のテストは純粋に機能的であり、スケーラビリティや「これを1年間使用した後に学んだ教訓」については何もありません.機能テスト コードは、次の CodePlex ページに示されています。この決定に進む前に、それを操作するためにクエリをどのように記述する必要があるかを理解する必要があります (フィールドまたは2 つ、ただし ない ほとんど/すべての文字列フィールド):
永続化された計算列と追加されたインデックスの数を考えると、スペースは本当に節約されましたか?;-)
スペース (ディスク、メモリなど) が問題になる場合は、次の 3 つのオプションがあります。
<オール> <リ>
SQL Server 2008 以降を使用していて、Enterprise Edition を使用している場合は、データ圧縮
.データ圧縮は、Unicode データを NCHAR
で圧縮できます (ただし、「常に」ではありません)。 および NVARCHAR
田畑。決定要因は次のとおりです。
NCHAR(1 - 4000)
および NVARCHAR(1 - 4000)
Unicode の標準圧縮方式
を使用する 、ただし SQL Server 2008 R2 以降のみで、かつ OVERFLOW ではなく、IN ROW データに対してのみです!これは、通常の ROW / PAGE 圧縮アルゴリズムよりも優れているようです。NVARCHAR(MAX)
および XML
(そして、VARBINARY(MAX)
も推測します) 、 TEXT
、および NTEXT
) IN ROW (LOB ページまたは OVERFLOW ページの行外ではない) のデータは、少なくとも PAGE 圧縮でき、おそらく ROW も圧縮されています (この最後のものについてはわかりません)。
2008 より古いバージョンを使用している場合、または Enterprise Edition ではない場合は、2 つのフィールドを持つことができます:1 つの VARCHAR
および 1 つの NVARCHAR
.たとえば、ほとんどすべてのベース ASCII 文字 (値 0 ~ 127) であり、したがって VARCHAR
に収まる URL を格納しているとします。 、ただし、Unicode 文字が含まれている場合があります。スキーマには次の 3 つのフィールドを含めることができます:
...
URLa VARCHAR(2048) NULL,
URLu NVARCHAR(2048) NULL,
URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])),
CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
([URLa] IS NOT NULL OR [URLu] IS NOT NULL)
AND ([URLa] IS NULL OR [URLu] IS NULL))
);
このモデルでは、のみ [URL]
から選択 計算列。挿入と更新の場合、変換によって NVARCHAR
でなければならない受信値が変更されるかどうかを確認して、使用するフィールドを決定します。 タイプ:
INSERT INTO TableName (..., URLa, URLu)
VALUES (...,
IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
);
<リ>
拡張 ASCII 文字セットの特定のコード ページに適合する文字のみを含む必要があるフィールドがある場合は、VARCHAR
を使用してください。 .
追記明確にするためにこれを述べておくと、新しい _SC
SQL Server 2012 で導入された照合順序では、以下が可能になります:
- 補助文字/サロゲート ペアを適切に処理するための組み込み関数
- 順序付けと比較に使用される補助文字の言語規則
しかし、新しい _SC
がなくても 照合、Unicode 文字を XML または N
に格納できます -接頭辞付きのタイプであり、データを失うことなく取得します。ただし、古い照合順序 (つまり、名前にバージョン番号がない) を使用すると、すべての補助文字が互いに同等になります。 _90
を使用する必要があります および _100
少なくともバイナリ/コードポイントの比較とソートを取得する照合。補助文字の特定のマッピングがない (したがって、重みや正規化規則がない) ため、言語規則を考慮に入れることができません。
以下を試してください:
IF (N'𤪆' = N'𤪆') SELECT N'𤪆' AS [TheLiteral], NCHAR(150150) AS [Generated];
IF (N'𤪆' = N'𤪇') SELECT N'𤪇' AS [TheLiteral], NCHAR(150151) AS [Generated];
IF (N'𤪆' COLLATE Tatar_90_CI_AI = N'𤪇' COLLATE Tatar_90_CI_AI)
SELECT N'𤪇 COLLATE Tatar_90_CI_AI' AS [TheLiteral], NCHAR(150151) AS [Generated];
IF (N'𤪆' = N'?') SELECT N'?';
_SC
で終わるデフォルトの照合を持つ DB 内 、最初の IF
のみ ステートメントは結果セットを返し、「Generated」フィールドには文字が正しく表示されます。
ただし、DB に _SC
で終わるデフォルトの照合がない場合 、および照合は _90
ではありません または _100
シリーズ照合、最初の 2 つの IF
ステートメントは、"Generated" フィールドが NULL
を返す結果セットを返します 、「リテラル」フィールドが正しく表示されます。
Unicode データの場合、Collation は物理ストレージには影響しません。
2018 年 10 月 2 日更新
これはまだ実行可能なオプションではありませんが、SQL Server 2019 では VARCHAR
で UTF-8 のネイティブ サポートが導入されています。 / CHAR
データ型。現在、使用するにはバグが多すぎますが、修正された場合、これは一部のオプションです シナリオ。私の投稿「SQL Server 2019 でのネイティブ UTF-8 サポート:救世主か偽預言者か?
"、この新機能の詳細な分析について。