web-dev-qa-db-ja.com

NVARCHARからVARCHARへの列の変換

多くのNVARCHAR(MAX)列を持ついくつかの大きなテーブルがあります。このデータベースは米国での使用のみを目的としており、どの列にも外国語の文字や文字は含まれていないと思います。そのため、次のことを調べたいと思います。

  1. これらの列の多くをNVARCHARからVARCHARに変更し、さらに
  2. 私が行ったいくつかのデータプロファイリングに基づいて、これらの列のサイズをより適切なサイズに変更します。たとえば、これらの列の一部のデータの最大長は約30文字しかないため、NVARCHAR(MAX)はやりすぎのように見えます。

また、暗黙的な変換を制限しようとしています。

各列に実際にVARCHARデータのみがあり、NVARCHARからの変換で問題が発生しない場合、これを行う前に簡単に判断する方法は何ですか?

2
equipe9

このデータベースは米国での使用のみを目的としており、どの列にも外国の文字や文字が含まれていないと思うので、調べたいと思います...これらの列の多くをNVARCHARからVARCHARに変更します

先に進む前に、これらの列のactualビジネス要件を調査/決定する必要があります。これらの列の1つ以上に現在VARCHARに簡単に収まらない文字が含まれていない場合でも、明日、Unicodeのみの文字を入力しようとしないわけではありません。 、そうすることは、システムの意図された設計の範囲外になります。エンドユーザー/営業担当者/サポート担当者/ドキュメントで、Unicodeのみの文字canがシステムに入力されていると思われる場合、その機能を誰も使用していなくても、システムはそれを許可する必要があります。まだ。これが事実であり、そのような文字を入力する必要がないと思うので変更する必要があると思われる場合は、それをマネージャー/プロダクトオーナーなどに提示する必要があります。

また、意図されたユーザーベースが米国にいるからといって、Unicodeのみの文字が使用されないという意味ではありません。少なくとも「名前」列、「説明」列などでは、さまざまなアクセント付き文字が簡単に存在したり、だれが何を知っているかがわかります。プロダクトオーナーやチームとの話し合いは、これらの各列/データポイントに必要なものを中心に展開する必要があります。

たとえば、これらの列の一部のデータの最大長は約30文字しかないため、NVARCHAR(MAX)はやり過ぎのようです。

これらの列で許可する必要がある文字の種類に関して上記で述べたポイントと同様に、最初に、システムが送信できる文字数を決定する必要があります。UIで説明フィールドが500〜1000文字に制限されている場合、およびコードの他の部分、そしてドキュメンテーション(いつでも希望することができますよね?)でさえ同意し、そうであれば絶対に、NVARCHAR(MAX)は完全に過剰です。ただし、列に8ビットのコードページで表されないさまざまな種類の4000文字以上を格納する必要がある場合、NVARCHAR(MAX)は過剰ではありません(ただし、格納よりも優れた設計を検討する必要がある場合があります) 1つのテーブルにそれらが多すぎます)。どちらの方法でも、特定のNVARCHAR(MAX)列には最大30文字しかないという事実は、製品所有者/チームに提供するのに適した情報であり、その列の運命に関してより情報に基づいた決定を行うことができます。おそらく、現在1000文字が許可されているが、最大レコード長が30から50のフィールドは、75から100までしか許可されないように更新する必要があります。ただし、調整する必要があります。

つまり、NVARCHAR/NCHAR/NTEXT列にVARCHARに変換できない文字があるかどうかを判断したい場合は、特定の列に使用されている照合の_BIN2バリエーションを使用してVARCHARに変換する必要があります。たとえば、特定の列がAlbanian_100_CI_ASを使用している場合、テストにはAlbanian_100_BIN2を指定します。 _BIN2照合を使用する理由は、非バイナリ照合では、コードページにマッピングがまったくなく、?に変換される文字が少なくとも1つあるインスタンスのみが検出されるためです。 。ただし、非バイナリ照合は、コードページへの直接マッピングを持たない文字が存在するインスタンスをキャッチせず、代わりに「最適な」マッピングを持ちます。たとえば、上付き文字2の文字²は、コードページ1252に直接マッピングされているため、問題はありません。一方、コードページ1250(アルバニア語の照合で使用)には直接のマッピングはありませんが、通常の2に変換する「最適な」マッピングがあります。非バイナリ照合の問題は、2²と同等であるため、VARCHARに変換できない行として登録されないことです。例えば:

SELECT CONVERT(VARCHAR(MAX), N'²' COLLATE French_100_CI_AS); -- Code Page 1252
-- ²
SELECT CONVERT(VARCHAR(MAX), N'²' COLLATE Albanian_100_CI_AS); -- Code Page 1250
-- 2

SELECT CONVERT(VARCHAR(MAX), N'²' COLLATE Albanian_100_CI_AS)
WHERE  N'²' <> CONVERT(NVARCHAR(MAX),
                       CONVERT(VARCHAR(MAX), N'²' COLLATE Albanian_100_CI_AS));
-- (no rows returned)

SELECT CONVERT(VARCHAR(MAX), N'²' COLLATE Albanian_100_BIN2)
WHERE  N'²' <> CONVERT(NVARCHAR(MAX),
                       CONVERT(VARCHAR(MAX), N'²' COLLATE Albanian_100_BIN2));
-- 2

理想的には、コードが何をしているかを明確にするためにNVARCHARに明示的に変換しますが、これを行わなくても暗黙的にNVARCHARに変換されるため、動作はどちらの方法でも同じです。

1
Solomon Rutzky

それらの列の多くがすでにNVARCHARにある場合、それは必ずしもそれらを変更する場所ではありません。 ASCIIコードはとにかくUNICODEコードページの先頭にあるためです。一方、NVARCHAR(MAX)は明らかに(非常に)悪いデザインのように見えます。列ごとにスクリプトを取得してみてください。実際のMAX​​とそこから変更します。ところで、これらのNVARCHAR(MAX)の一部は実際にあるはずです... CHAR(5);それが10未満の長さの場合は、固定長の文字列が推奨されます。最初に小さいものを探し、キーを確認します(参加時間も節約したいですか?)

何かの最大値が30の場合、おそらくそれがアプリに必要な最大値です。 NVARCHAR(100)にして(フリーテキストフィールドの場合、誰かがフランス語のテキストを入力する可能性があります)、正しい長さであると確信できます。

ところで、これがデータベースの設計方法である場合は、int /数値フィールドも確認してください。 smallintまたはtinyintで十分な場合にBIGINTを使用する理由

0
Hila DG

ASCII(VARCHAR)でサポートされていない文字列を見つけるselectステートメントを探していると思いますが、正しいですか?

以下で参照する回答は、そのようなステートメントを提供します(いくつかのサンプルテーブル構造を使用)。このステートメントは、NVARCHAR(Unicode)として格納した値と、VARCHAR(ASCII)と同じ値キャストを比較します。クエリが何も返さない場合は、変換しても問題ありません。行にVARCHARとして格納されている値とは異なる値を持つ列が含まれている場合、その値が返されます。
以下の別の回答から例をコピーしました:

SELECT NAME, ADDRESS, DESCRIPTION
FROM DBO.USERS
WHERE NAME != CAST(NAME AS VARCHAR(4000))
OR ADDRESS != CAST(ADDRESS AS VARCHAR(4000))
OR DESCRIPTION != CAST(DESCRIPTION AS VARCHAR(4000))

https://stackoverflow.com/a/29819626/10340388

0
Superman.Lopez

おそらく、最後の段階で値をvarbinaryにキャストするequipe9の投稿の変更ですか?何かのようなもの

CAST(NAME AS binary(max))!= CAST(CAST(NAME AS VARCHAR(4000))AS binary(max))

テストせず、大声で考えて、追加する必要があります...

別のオプションとして、行の圧縮をオンにすることもできます。これは、(2008R2以降)Unicode圧縮に付属しています。そうすれば、「普通の」キャラクターに対してはるかに安い料金を支払うことができます。

0
Tibor Karaszi