1

Transcat SQL について質問がありました。以下は SQL コードです。

DECLARE @main nVARCHAR(max);

--there are over 4000 characters to @main 
set @main = '01234567890123456789...';
Print len(@main)

@main の長さは正しいですが、コードを以下のように変更すると、たとえば 4007 になります。

DECLARE @main nVARCHAR(max);

--there are over 4000 characters to @main 
set @main = N'01234567890123456789...';
Print len(@main)

@main の長さは常に 4000 になります。これは奇妙で、わかりません。別のことは、コードを以下に変更した場合です。

DECLARE @main nVARCHAR(max), @split nVARCHAR(500);

--there are 500 characters to @split 
set @split = '01234567890123456789...';
set @main = @split + @split + @split + @split + @split + @split + @split + @split + @split + @split;
Print len(@main)

@main の長さが 4000 ですが、なぜですか? 「01234567890123456789...」の前に文字 N を追加しても問題ありませんか? @split を varchar(500) DECLARE @main nVARCHAR(max), @split VARCHAR(500); に変更すると、

--there are 500 characters to @split 
set @split = '01234567890123456789...';
-- 10 @split
set @main = @split + @split + @split + @split + @split + @split + @split + @split + @split + @split;
Print len(@main)

@main の長さは正しいです。''01234567890123456789...' の前に文字 N を追加してもしなくても、@main の長さは常に 5000 です

4

1 に答える 1

1

文字列式の暗黙的な型で問題が発生しています。MAX長さを除いて、VARCHAR型は 8000 文字 (SQL SERVER のページのサイズによって制限されます) をNVARCHAR保持でき、2 バイト文字を格納するため、文字数の半分 (4000) を保持できます。デフォルトでは、文字列式 (リテラル、連結文字列など) は、 for の最大長 8000varcharまたは4000forの最大長のいずれかを使用して評価されnvarcharます。MAX期待する動作を得るには、式を型に明示的にキャストする必要があります。

最初の例では、文字列式'01234567890123456789...'は として暗黙的に評価され、VARCHAR(8000)その後暗黙的に変換されるNVARCHAR(MAX)ため、式には 4007 文字しかないため、文字数が正しく保持されます。

文字列式を Unicode に変換すると (つまり、値を変数に代入する前N'01234567890123456789...'と同じように文字列が評価されます。NVARCHAR(4000)NVARCHAR(MAX)

2 番目の例を次のように変更します。

DECLARE @main nVARCHAR(max);

--there are over 4000 characters to @main 
set @main = CAST(N'01234567890123456789...' AS NVARCHAR(MAX));
Print len(@main)

そして、期待どおりに動作します。

同様に、変数を連結している場合、式を次のように評価するには、左端の値をキャストする必要があるため@split、SQL Server は式を評価しています。NVARCHAR(4000)NVARCHAR(MAX)NVARCHAR(MAX)

DECLARE @main nVARCHAR(max), @split nVARCHAR(500);

--there are 500 characters to @split 
set @split = '01234567890123456789...';
set @main = CAST(@split as NVARCHAR(MAX)) + @split + @split + @split + @split + @split + @split + @split + @split + @split;
Print len(@main)

それが動作します。

于 2011-11-14T05:12:46.383 に答える