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.
varchar(n) + varchar(n)
se truncará en 8000 caracteres.nvarchar(n) + nvarchar(n)
se truncará en 4000 caracteres.varchar(n) + nvarchar(n)
se truncará en 4.000 caracteres.nvarchar
tiene mayor prioridad por lo que el resultado esnvarchar(4,000)
[n]varchar(max)
+[n]varchar(max)
no se truncará (para <2 GB).varchar(max)
+varchar(n)
no se truncará (para <2 GB) y el resultado se escribirá comovarchar(max)
.varchar(max)
+nvarchar(n)
no se truncará (para <2 GB) y el resultado se escribirá comonvarchar(max)
.nvarchar(max)
+varchar(n)
primero convertirá elvarchar(n)
entrada anvarchar(n)
y luego hacer la concatenación. Si la longitud delvarchar(n)
la cadena tiene más de 4000 caracteres, la conversión será paranvarchar(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.
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.
+=
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 <
apareciendo como <
.