【问题标题】:The weird length of varchar and nvarchar in T-SQLT-SQL 中 varchar 和 nvarchar 的奇怪长度
【发布时间】:2011-11-14 00:24:51
【问题描述】:

我有一个关于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

【问题讨论】:

    标签: tsql varchar nvarchar


    【解决方案1】:

    您遇到了字符串表达式的隐式类型的问题。除了MAX 长度之外,VARCHAR 类型可以容纳 8000 个字符(受 SQL SERVER 中页面大小的限制),并且因为NVARCHAR 存储双字节字符,它可以容纳一半的字符数(4000)。默认情况下,使用varchar 的最大长度8000 或nvarchar4000 的最大长度来评估字符串表达式(文字、串联字符串等)。您必须将表达式显式转换为 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)
    

    它会起作用的。

    【讨论】:

    • 我测试了你修改的sql脚本,结果和我原来的例子一样。
    • 我刚刚用一个 10,000 个字符的字符串运行了我的第一个示例,按预期工作。我运行了我的第二个示例,@split 是一个 500 字符的字符串,它按预期工作。
    猜你喜欢
    • 2011-03-04
    • 2020-03-02
    • 2021-10-12
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-26
    相关资源
    最近更新 更多