sql >> Base de Datos >  >> RDS >> Sqlserver

Límites de SQL NVARCHAR y VARCHAR

Entiendo que hay un conjunto máximo de 4000 para NVARCHAR(MAX)

Tu comprensión es incorrecta. nvarchar(max) puede almacenar hasta (y más a veces) 2 GB de datos (mil millones de caracteres de doble byte).

De nchar y nvarchar en Libros en línea, la gramática es

nvarchar [ ( n | max ) ]

El | carácter significa que estas son alternativas. es decir, especifica cualquiera n o el literal max .

Si elige especificar un n específico entonces esto debe estar entre 1 y 4000 pero usando max lo define como un tipo de datos de objeto grande (reemplazo de ntext que está en desuso).

De hecho en SQL Server 2008 parece que para una variable el límite de 2GB se puede exceder indefinidamente sujeto a espacio suficiente en tempdb (Se muestra aquí)

Con respecto a las otras partes de su pregunta

El truncamiento al concatenar depende del tipo de datos.

  1. varchar(n) + varchar(n) se truncará en 8000 caracteres.
  2. nvarchar(n) + nvarchar(n) se truncará en 4000 caracteres.
  3. varchar(n) + nvarchar(n) se truncará en 4.000 caracteres. nvarchar tiene mayor prioridad por lo que el resultado es nvarchar(4,000)
  4. [n]varchar(max) + [n]varchar(max) no se truncará (para <2 GB).
  5. varchar(max) + varchar(n) no se truncará (para <2 GB) y el resultado se escribirá como varchar(max) .
  6. varchar(max) + nvarchar(n) no se truncará (para <2 GB) y el resultado se escribirá como nvarchar(max) .
  7. nvarchar(max) + varchar(n) primero convertirá el varchar(n) entrada a nvarchar(n) y luego hacer la concatenación. Si la longitud del varchar(n) la cadena tiene más de 4000 caracteres, la conversión será para nvarchar(4000) y se producirá un truncamiento .

Tipos de datos de cadenas literales

Si usa el N prefijo y la cadena tiene <=4000 caracteres, se escribirá como nvarchar(n) donde n es la longitud de la cadena. Así que N'Foo' será tratado como nvarchar(3) por ejemplo. Si la cadena tiene más de 4000 caracteres, se tratará como nvarchar(max)

Si no usa el N prefijo y la cadena tiene <=8000 caracteres, se escribirá como varchar(n) donde n es la longitud de la cadena. Si es más largo como varchar(max)

Para los dos anteriores, si la longitud de la cadena es cero, entonces n se establece en 1.

Elementos de sintaxis más nuevos.

1. El CONCAT la función no ayuda aquí

DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);

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

Lo anterior devuelve 8000 para ambos métodos de concatenación.

2. Tenga cuidado con +=

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);`

Devoluciones

-------------------- --------------------
8000                 10000

Tenga en cuenta que @A encontró truncamiento.

Cómo resolver el problema que está experimentando.

Obtiene truncamiento porque está concatenando dos no max tipos de datos juntos o porque está concatenando un varchar(4001 - 8000) cadena a un nvarchar cadena escrita (incluso nvarchar(max) ).

Para evitar el segundo problema, simplemente asegúrese de que todos los literales de cadena (o al menos aquellos con longitudes en el rango de 4001 - 8000) estén precedidos por N .

Para evitar el primer problema, cambie la asignación de

DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;

Para

DECLARE @SQL NVARCHAR(MAX) = ''; 
SET @SQL = @SQL + N'Foo' + N'Bar'

para que un NVARCHAR(MAX) está involucrado en la concatenación desde el principio (ya que el resultado de cada concatenación también será NVARCHAR(MAX) esto se propagará)

Evitar el truncamiento al visualizar

Asegúrese de tener seleccionado el modo "resultados a la cuadrícula" y luego puede usar

select @SQL as [processing-instruction(x)] FOR XML PATH 

Las opciones de SSMS le permiten establecer una longitud ilimitada para XML resultados. La processing-instruction bit evita problemas con caracteres como &lt; apareciendo como &lt; .