T-SQL中varchar和nvarchar的奇怪长度

时间:2011-11-14 00:24:51

标签: tsql varchar nvarchar

我对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

1 个答案:

答案 0 :(得分:1)

您遇到了隐式字符串表达式问题。除MAX长度外,VARCHAR类型可以容纳8000个字符(受SQL SERVER中页面大小的限制),并且因为NVARCHAR存储双字节字符,它可以保持一半的字符数(4000)。默认情况下,使用varchar的最大长度为8000或4000的最大长度为nvarchar来计算字符串表达式(文字,连接字符串等)。您必须将表达式显式转换为MAX类型以获得您期望的行为。

在第一个示例中,您的字符串表达式'01234567890123456789...'被隐式计算为VARCHAR(8000),然后隐式转换为NVARCHAR(MAX),因此它正确地保留了字符数,因为您的表达式只有4007个字符。

当您将字符串表达式转换为unicode时(即N'01234567890123456789...',它会在将值分配给NVARCHAR(4000)变量之前将字符串计算为NVARCHAR(MAX)

将您的第二个示例更改为:

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)

它会起作用。