Eu entendo que há um máximo de 4000 definido para NVARCHAR(MAX)
Seu entendimento está errado. nvarchar(max)
pode armazenar até (e às vezes além) 2 GB de dados (1 bilhão de caracteres de byte duplo).
De nchar e nvarchar em Livros online, a gramática é
nvarchar [ ( n | max ) ]
O |
personagem significa que essas são alternativas. ou seja, você especifica um n
ou o literal max
.
Se você optar por especificar um específico n
, ele deve estar entre 1 e 4.000, mas o uso o max
define como um tipo de dados de objeto grande (substituição para o ntext
qual está obsoleto).
Na verdade, no SQL Server 2008, parece que para uma variável o limite de 2 GB pode ser excedido indefinidamente, sujeito a espaço suficiente em tempdb
( mostrado aqui )
Em relação às outras partes da sua pergunta
O truncamento durante a concatenação depende do tipo de dados.
varchar(n) + varchar(n)
irá truncar em 8.000 caracteres.
nvarchar(n) + nvarchar(n)
irá truncar em 4.000 caracteres.
varchar(n) + nvarchar(n)
irá truncar em 4.000 caracteres. nvarchar
tem maior precedência, então o resultado énvarchar(4,000)
[n]varchar(max)
+ [n]varchar(max)
não truncará (para <2 GB).
varchar(max)
+ varchar(n)
não truncará (para <2 GB) e o resultado será digitado como varchar(max)
.
varchar(max)
+ nvarchar(n)
não truncará (para <2 GB) e o resultado será digitado como nvarchar(max)
.
nvarchar(max)
+ varchar(n)
primeiro converterá a varchar(n)
entrada para nvarchar(n)
e, em seguida, fará a concatenação. Se o comprimento da varchar(n)
string for maior que 4.000 caracteres, a conversão será para nvarchar(4000)
e ocorrerá truncamento .
Tipos de dados de literais de string
Se você usar o N
prefixo e a string tiver <= 4.000 caracteres, ela será digitada como nvarchar(n)
onde n
é o comprimento da string. Portanto N'Foo'
, será tratado como nvarchar(3)
exemplo. Se a string tiver mais de 4.000 caracteres, ela será tratada comonvarchar(max)
Se você não usar o N
prefixo e a string tiver <= 8.000 caracteres, ela será digitada como varchar(n)
onde n
é o comprimento da string. Se mais comovarchar(max)
Para ambos os itens acima, se o comprimento da string for zero, n
será definido como 1.
Elementos de sintaxe mais recentes.
1. A CONCAT
função não ajuda aqui
DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);
SELECT DATALENGTH(@A5000 + @A5000),
DATALENGTH(CONCAT(@A5000,@A5000));
O código acima retorna 8000 para ambos os métodos de concatenação.
2. Tenha cuidado com+=
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);`
Devoluções
-------------------- --------------------
8000 10000
Observe que @A
encontrou truncamento.
Como resolver o problema que você está enfrentando.
Você está obtendo truncamento porque está concatenando dois max
tipos que não são de dados ou porque está concatenando uma varchar(4001 - 8000)
string com uma nvarchar
string digitada (par nvarchar(max)
).
Para evitar o segundo problema, simplesmente certifique-se de que todos os literais de string (ou pelo menos aqueles com comprimentos no intervalo 4001 - 8000) sejam precedidos por N
.
Para evitar o primeiro problema, altere a atribuição de
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;
Para
DECLARE @SQL NVARCHAR(MAX) = '';
SET @SQL = @SQL + N'Foo' + N'Bar'
de modo que um NVARCHAR(MAX)
esteja envolvido na concatenação desde o início (como o resultado de cada concatenação também será, NVARCHAR(MAX)
isso se propagará)
Evitando truncamento ao visualizar
Certifique-se de ter selecionado o modo "resultados para grade", então você pode usar
select @SQL as [processing-instruction(x)] FOR XML PATH
As opções de SSMS permitem que você defina uma duração ilimitada para os XML
resultados. O processing-instruction
bit evita problemas com personagens como <
aparecer como <
.