Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Limites SQL NVARCHAR e VARCHAR


Entendo que há um conjunto máximo de 4000 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 | caractere significa que estas são alternativas. ou seja, você especifica ou n ou o literal max .

Se você optar por especificar um n específico então isso deve estar entre 1 e 4.000, mas usando max define-o como um tipo de dados de objeto grande (substituto para ntext que está obsoleto).

De fato, 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 ao concatenar depende do tipo de dados.

  1. varchar(n) + varchar(n) será truncado em 8.000 caracteres.
  2. nvarchar(n) + nvarchar(n) será truncado em 4.000 caracteres.
  3. varchar(n) + nvarchar(n) truncará em 4.000 caracteres. nvarchar tem maior precedência, então o resultado é nvarchar(4,000)
  4. [n]varchar(max) + [n]varchar(max) não será truncado (para <2 GB).
  5. varchar(max) + varchar(n) não truncará (para <2 GB) e o resultado será digitado como varchar(max) .
  6. varchar(max) + nvarchar(n) não truncará (para <2 GB) e o resultado será digitado como nvarchar(max) .
  7. nvarchar(max) + varchar(n) primeiro converterá o varchar(n) entrada para nvarchar(n) e depois faça a concatenação. Se o comprimento do varchar(n) string for maior que 4.000 caracteres, a conversão será para nvarchar(4000) e o truncamento ocorrerá .

Tipos de dados de literais de string


Se você usar o N prefixo e a string tem <=4.000 caracteres, ela será digitada como nvarchar(n) onde n é o comprimento da corda. Então N'Foo' será tratado como nvarchar(3) por exemplo. Se a string tiver mais de 4.000 caracteres, ela será tratada como nvarchar(max)

Se você não usar o N prefixo e a string tem <=8.000 caracteres, ela será digitada como varchar(n) onde n é o comprimento da corda. Se mais longo como varchar(max)

Para ambos os itens acima, se o comprimento da string for zero, n é definido como 1.

Elementos de sintaxe mais recentes.


1. O CONCAT função não ajuda aqui
DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);

SELECT DATALENGTH(@A5000 + @A5000), 
       DATALENGTH(CONCAT(@A5000,@A5000));

O 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 não max tipos de dados juntos ou porque você está concatenando um varchar(4001 - 8000) string para um nvarchar string digitada (mesmo 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'

para que um NVARCHAR(MAX) está envolvido na concatenação desde o início (pois o resultado de cada concatenação também será NVARCHAR(MAX) isso vai se propagar)

Evitando truncamento ao visualizar


Certifique-se de ter o modo "resultados para grade" selecionado, então você pode usar
select @SQL as [processing-instruction(x)] FOR XML PATH 

As opções do SSMS permitem definir comprimento ilimitado para XML resultados. A processing-instruction bit evita problemas com caracteres como &lt; aparecendo como &lt; .