Я так понимаю, что для NVARCHAR(MAX)
Ваше понимание неверно. nvarchar(max)
может хранить до (а иногда и больше) 2 ГБ данных (1 миллиард двухбайтовых символов).
Из nchar и nvarchar в Книгах онлайн грамматика
nvarchar [ ( n | max ) ]
Символ |
означает, что это альтернативы. т.е. вы указываете либо n
буквальное, либо буквальное max
.
Если вы решите указать конкретное значение, n
оно должно быть от 1 до 4000, но использование max
определяет его как тип данных большого объекта (замена ntext
которого устарела).
Фактически в SQL Server 2008 кажется, что для переменной ограничение в 2 ГБ может быть превышено на неопределенное время при условии наличия достаточного места в tempdb
( показано здесь )
Что касается других частей вашего вопроса
Усечение при объединении зависит от типа данных.
varchar(n) + varchar(n)
будет обрезано до 8000 символов.
nvarchar(n) + nvarchar(n)
будет обрезано до 4000 символов.
varchar(n) + nvarchar(n)
будет обрезано до 4000 символов. nvarchar
имеет более высокий приоритет, поэтому результатnvarchar(4,000)
[n]varchar(max)
+ [n]varchar(max)
не обрезается (для <2 ГБ).
varchar(max)
+ varchar(n)
не будет усекаться (для <2 ГБ), и результат будет напечатан как varchar(max)
.
varchar(max)
+ nvarchar(n)
не будет усекаться (для <2 ГБ), и результат будет напечатан как nvarchar(max)
.
nvarchar(max)
+ varchar(n)
сначала преобразует varchar(n)
ввод, nvarchar(n)
а затем выполнит конкатенацию. Если длина varchar(n)
строки превышает 4000 символов, будет выполнено приведение nvarchar(4000)
и произойдет усечение .
Типы данных строковых литералов
Если вы используете N
префикс и длина строки <= 4000 символов, она будет набрана как nvarchar(n)
где n
- длина строки. Так N'Foo'
будем относиться nvarchar(3)
к примеру. Если строка длиннее 4000 символов, она будет рассматриваться какnvarchar(max)
Если вы не используете N
префикс и длина строки <= 8000 символов, она будет набрана как varchar(n)
где n
- длина строки. Если дольше, какvarchar(max)
В обоих случаях, если длина строки равна нулю, n
устанавливается значение 1.
Новые элементы синтаксиса.
1.CONCAT
функция здесь не поможет
DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);
SELECT DATALENGTH(@A5000 + @A5000),
DATALENGTH(CONCAT(@A5000,@A5000));
Приведенное выше возвращает 8000 для обоих методов конкатенации.
2. Будьте осторожны с+=
DECLARE @A VARCHAR(MAX) = '';
SET @A+= REPLICATE('A',5000) + REPLICATE('A',5000)
DECLARE @B VARCHAR(MAX) = '';
SET @B = @B + REPLICATE('A',5000) + REPLICATE('A',5000)
SELECT DATALENGTH(@A),
DATALENGTH(@B);`
Возврат
-------------------- --------------------
8000 10000
Обратите внимание, что @A
обнаружено усечение.
Как решить возникшую проблему.
Вы получаете усечение либо потому, что вы объединяете два не max
типа данных вместе, либо потому, что вы объединяете varchar(4001 - 8000)
строку с nvarchar
типизированной строкой (даже nvarchar(max)
).
Чтобы избежать второй проблемы, просто убедитесь, что все строковые литералы (или хотя бы те, длина которых находится в диапазоне от 4001 до 8000) имеют префикс N
.
Чтобы избежать первой проблемы, измените назначение с
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;
Чтобы
DECLARE @SQL NVARCHAR(MAX) = '';
SET @SQL = @SQL + N'Foo' + N'Bar'
так что an NVARCHAR(MAX)
участвует в конкатенации с самого начала (поскольку результат каждой конкатенации также NVARCHAR(MAX)
будет распространяться)
Избегайте усечения при просмотре
Убедитесь, что у вас выбран режим «результаты в сетку», тогда вы можете использовать
select @SQL as [processing-instruction(x)] FOR XML PATH
Параметры SSMS позволяют установить неограниченную длину XML
результатов. processing-instruction
Бит позволяет избежать проблем с символами , такими как <
показ , как <
.