[解決済み] SQLのNVARCHARとVARCHARの限界値
質問
大きな(避けられない)動的SQLクエリを持っています。選択基準のフィールドの数が多いため、動的 SQL を含む文字列が 4000 文字以上に増えています。現在、私は、最大 4000 文字が
NVARCHAR(MAX)
に 4000 の最大値が設定されていることは理解していますが、Server Profiler で実行された SQL を見てみると、ステートメントは
DELARE @SQL NVARCHAR(MAX);
SET @SQL = 'SomeMassiveString > 4000 chars...';
EXEC(@SQL);
GO
動作しているように見えますが(!?)、同じく大きな別のクエリでは、この4000の制限(!?)に関連したエラーが投げられます。基本的に、この4000の制限以降のすべてのSQLが切り捨てられ、構文エラーが残されます。プロファイラでは、この動的SQLクエリは full (!?).
ここで一体何が起こっているのでしょうか、そして私はこの@SQL変数をVARCHARに変換して取り掛かればよいのでしょうか。
お時間をいただきありがとうございました。
Ps. また、これらの大きなクエリを見るために、4000文字以上の印刷ができるといいのですが。以下は4000に制限されています。
SELECT CONVERT(XML, @SQL);
PRINT(@SQL);
他にいい方法はないのでしょうか?
どのように解決するのですか?
<ブロッククオート
の最大値が4000に設定されていることは理解しています。
NVARCHAR(MAX)
あなたの理解は間違っています。
nvarchar(max)
は最大 2GB (場合によってはそれ以上) のデータ (10億ダブルバイト文字) を格納することができます。
から nchar および nvarchar の文法は、Books online では
nvarchar [ ( n | max ) ]
は
|
の文字は、これらが選択肢であることを意味します。
のどちらかを
n
またはリテラル
max
.
もし、特定の
n
を指定する場合、これは 1 から 4,000 の間でなければなりません。
max
を使うとラージオブジェクトのデータ型として定義されます。
ntext
の置き換え)。
実際、SQL Server 2008 では
変数
において十分なスペースがあれば、2GB の制限を無制限に超えることができるようです。
tempdb
(
ここに表示されます
)
ご質問の他の部分について
連結時の切り捨てはデータ型に依存します。
-
varchar(n) + varchar(n)
は8,000文字で切り捨てられます。 -
nvarchar(n) + nvarchar(n)
は4,000文字で切り捨てられます。 -
varchar(n) + nvarchar(n)
は4,000文字で切り捨てられます。nvarchar
の方が優先順位が高いので、結果はnvarchar(4,000)
-
[n]varchar(max)
+[n]varchar(max)
は切り捨てられません(< 2GBの場合)。 -
varchar(max)
+varchar(n)
は切り捨てられず(2GBの場合)、結果は次のように入力されます。varchar(max)
. -
varchar(max)
+nvarchar(n)
は切り捨てられず(2GBの場合)、結果は次のように入力されます。nvarchar(max)
. -
nvarchar(max)
+varchar(n)
は、まずvarchar(n)
への入力をnvarchar(n)
と入力し、連結を行う。 の長さが足りない場合はvarchar(n)
の文字列の長さが4,000文字より大きい場合、キャストはnvarchar(4000)
にキャストされ、切り捨てが行われます。 .
文字列リテラルのデータ型
もしあなたが
N
を使い、文字列の長さが <= 4,000 文字の場合、次のように入力されます。
nvarchar(n)
ここで
n
は文字列の長さです。つまり
N'Foo'
として扱われます。
nvarchar(3)
のように扱われます。文字列が4,000文字より長い場合、以下のように扱われます。
nvarchar(max)
を使用しない場合は
N
を使わず、文字列の長さが <= 8,000 文字の場合、次のように入力されます。
varchar(n)
ここで
n
は文字列の長さです。より長い場合は
varchar(max)
上記のどちらも、文字列の長さがゼロの場合は
n
は1に設定されます。
新しい構文要素です。
1.
は
CONCAT
関数はここでは役に立ちません
DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);
SELECT DATALENGTH(@A5000 + @A5000),
DATALENGTH(CONCAT(@A5000,@A5000));
上記は、連結のどちらの方法でも8000を返します。
2.
注意すべきは
+=
DECLARE @A VARCHAR(MAX) = '';
SET @A+= REPLICATE('A',5000) + REPLICATE('A',5000)
DECLARE @B VARCHAR(MAX) = '';
SET @B = @B + REPLICATE('A',5000) + REPLICATE('A',5000)
SELECT DATALENGTH(@A),
DATALENGTH(@B);`
戻り値
-------------------- --------------------
8000 10000
なお
@A
は切り捨てに遭遇したことに注意してください。
発生している問題を解決する方法。
切り捨てが発生するのは、2つの非対称な
max
データ型を連結しているか、または
varchar(4001 - 8000)
の文字列を
nvarchar
のような型付けされた文字列(たとえ
nvarchar(max)
).
2番目の問題を避けるには、すべての文字列リテラル(少なくとも4001から8000の範囲の長さのもの)の前に、単純に
N
.
最初の問題を回避するために、割り当てを
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;
への
DECLARE @SQL NVARCHAR(MAX) = '';
SET @SQL = @SQL + N'Foo' + N'Bar'
というように
NVARCHAR(MAX)
は最初から連結に関与しています(各連想の結果もまた
NVARCHAR(MAX)
となり、伝播していきます)
表示時の切り詰めを回避する
グリッドに結果を表示するモードが選択されていることを確認してください。
select @SQL as [processing-instruction(x)] FOR XML PATH
SSMSのオプションで、長さを無制限に設定できるのは
XML
の結果を表示します。そのため
processing-instruction
のような文字の問題を回避することができます。
<
のように表示されます。
<
.
関連
-
[解決済み] SQL ServerでSELECTからUPDATEする方法とは?
-
[解決済み] PHPでSQLインジェクションを防ぐにはどうしたらいいですか?
-
[解決済み] SQL Server で複数行のテキストを 1 つのテキスト文字列に連結する方法
-
[解決済み] SQL Server テーブルにカラムが存在するかどうかを確認する方法は?
-
[解決済み] varcharとnvarcharの違いは何ですか?
-
[解決済み] SQL Serverで、指定したテーブルを参照しているすべての外部キーを一覧表示するにはどうすればよいですか?
-
[解決済み] T-SQL文の接頭辞Nの意味と使うべきタイミングは?
-
[解決済み】「INNER JOIN」と「OUTER JOIN」の違いは何ですか?
-
[解決済み】SQL Serverで既存のテーブルにデフォルト値を持つカラムを追加する
-
[解決済み] SQL ServerでINNER JOINを使用して削除するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
MHAの高可用性構成とフェイルオーバー
-
windows mysql prompt access denied for user ''@'localhost' to database.
-
executeQuery()ソリューションでデータ操作文を発行できない。
-
[解決済み] ストアドプロシージャ 'dbo.aspnet_CheckSchemaVersion' が見つかりませんでした。
-
[解決済み] SQLの結合形式 - 入れ子になった内側join
-
[解決済み] SQLのSELECTでIF...THENを実行するにはどうすればよいですか?
-
[解決済み] 複数の列でgroup byを使用する
-
[解決済み] SQL Serverには、.NETのMath.Maxのような2つの値を取るMax関数はありますか?
-
[解決済み] DISTINCTでCOUNT(*)を選択する
-
[解決済み] SQL Serverで、ある日付より大きいすべての日付を照会するにはどうすればよいですか?