У вас проблемы с неявными типами строковых выражений. За исключением длины MAX
, тип VARCHAR
может содержать 8000 символов (ограничено размером страницы в SQL SERVER) и, поскольку NVARCHAR
хранит двухбайтовые символы, он может содержать половину числа символов (4000). По умолчанию строковые выражения (литералы, объединенные строки и т. Д.) Оцениваются с использованием максимальной длины 8000 для varchar
или максимальной длины 4000
для nvarchar
. Вы должны явно привести выражение к типу MAX
, чтобы получить ожидаемое поведение.
В первом примере ваше строковое выражение '01234567890123456789...'
неявно оценивается как VARCHAR(8000)
, которое затем неявно преобразуется в NVARCHAR(MAX)
, поэтому оно правильно сохраняет количество символов, поскольку в вашем выражении только 4007 символов.
Когда вы преобразуете строковое выражение в юникод (то есть 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)
Это будет работать.