Разбирам, че има 4000 максимален набор за
NVARCHAR(MAX)
Вашето разбиране е погрешно. nvarchar(max)
може да съхранява до (а понякога и повече) 2GB данни (1 милиард двойни байтови знака).
От nchar и nvarchar в Books online граматиката е
nvarchar [ ( n | max ) ]
|
характер означава, че това са алтернативи. т.е. посочвате и двете n
или литералът max
.
Ако изберете да посочите конкретен n
тогава това трябва да е между 1 и 4000, но с помощта на max
го дефинира като тип данни за голям обект (замяна на ntext
който е отхвърлен).
Всъщност в SQL Server 2008 изглежда, че за променлива ограничението от 2 GB може да бъде надвишено за неопределено време при условие на достатъчно място в 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)
няма да се съкращава (за <2GB).varchar(max)
+varchar(n)
няма да се съкращава (за <2GB) и резултатът ще бъде въведен катоvarchar(max)
.varchar(max)
+nvarchar(n)
няма да се съкращава (за <2GB) и резултатът ще бъде въведен като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'
така че NVARCHAR(MAX)
участва в конкатенацията от самото начало (като резултатът от всяка конкатенация също ще бъде NVARCHAR(MAX)
това ще се разпространи)
Избягване на съкращаване при преглед
Уверете се, че сте избрали режим "резултати към мрежа", след което можете да използвате
select @SQL as [processing-instruction(x)] FOR XML PATH
Опциите за SSMS ви позволяват да зададете неограничена дължина за XML
резултати. processing-instruction
bit избягва проблеми със знаци като <
показва се като <
.