The weird length of varchar and nvarchar in T-SQL

若如初见. 提交于 2019-12-11 06:46:50

问题


I had a question about the Transcat SQL, below is the sql code;

DECLARE @main nVARCHAR(max);

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

the length of @main is correct, e.g. 4007 however, if I change the code to below:

DECLARE @main nVARCHAR(max);

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

the length of @main will always be 4000, it is weird, I don't understand. Another thing is if I change the code to below:

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)

The length of @main is 4000, why? No matter I add letter N before '01234567890123456789...'? if I change the @split to 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)

The length of @main is correct, no matter I add letter N before ''01234567890123456789...' or not, the length of @main is always 5000


回答1:


You're running into issues with implicit types of string expressions. With the exception of MAX lengths, a VARCHAR type can hold 8000 chars (limited by the size of a page in SQL SERVER) and, because NVARCHAR stores double-byte chars, it can hold half the number of chars (4000). By default string expressions (literals, concatenated strings etc) are evaluated using either a max length of 8000 for varchar or a max len of 4000 for nvarchar. You have to explicitly cast the expression to a MAX type to get the behavior you expect.

In your first example, your string expression '01234567890123456789...' is implicitly evaluated as a VARCHAR(8000) which is then implicitly converted to NVARCHAR(MAX) so it correctly retains the number of characters since your expression only had 4007 chars.

When you convert your string expression to unicode (i.e. N'01234567890123456789...' it evaluates the string as NVARCHAR(4000) before assigning the value to your NVARCHAR(MAX) variable.

Change your second example to this:

DECLARE @main nVARCHAR(max);

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

And it will behave as you expect.

Likewise when you're concatenating the @split variables, SQL Server is evaluating the expression as NVARCHAR(4000) you have to cast the leftmost value as NVARCHAR(MAX) in order to have the expression evaluated as 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)

It will work.



来源:https://stackoverflow.com/questions/8115972/the-weird-length-of-varchar-and-nvarchar-in-t-sql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!