Inspirado por la respuesta de @Paul , investigué un poco y descubrí que si bien es cierto que el espacio de pila limita el número de concatenaciones, y que el espacio de pila es una función de la memoria disponible y, por lo tanto, varía, los siguientes dos puntos también son ciertos :
- hay una manera de agrupar concatenaciones adicionales en una sola declaración, Y
- usando este método para ir más allá de la limitación inicial de espacio de pila, se puede encontrar un límite lógico real (que no parece variar)
Primero, adapté el código de prueba de Paul para concatenar cadenas:
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = N'
DECLARE @S VARCHAR(MAX), @A VARCHAR(MAX) = ''a'';
SET @S = @A';
SET @SQL += REPLICATE(CONVERT(NVARCHAR(MAX), N' + @A'), 3312) + N';';
-- SET @S = @A + @A + @A...
SET @SQL += N'SELECT DATALENGTH(@S) AS [Chars In @S];';
EXECUTE (@SQL);
Con esta prueba, lo más alto que pude obtener al ejecutar en mi portátil no tan bueno (solo 6 GB de RAM) fue:
- 3311 (devuelve 3312 caracteres totales) usando SQL Server 2017 Express Edition LocalDB (14.0.3006)
- 3512 (devuelve 3513 caracteres en total) con SQL Server 2012 Developer Edition SP4 (KB4018073) (11.0.7001)
antes de obtener el error 8631 .
Luego, intenté agrupar las concatenaciones usando paréntesis de modo que la operación concatenara múltiples grupos de concatenaciones. Por ejemplo:
SET @S = (@A + @A + @A + @A) + (@A + @A + @A + @A) + (@A + @A + @A + @A);
Al hacerlo, pude ir mucho más allá de los límites anteriores de las variables 3312 y 3513. El código actualizado es:
DECLARE @SQL VARCHAR(MAX), @Chunk VARCHAR(MAX);
SET @SQL = '
DECLARE @S VARCHAR(MAX), @A VARCHAR(MAX) = ''a'';
SET @S = (@A+@A)';
SET @Chunk = ' + (@A' + REPLICATE(CONVERT(VARCHAR(MAX), '+@A'), 42) + ')';
SET @SQL += REPLICATE(CONVERT(VARCHAR(MAX), @Chunk), 762) + ';';
SET @SQL += 'SELECT DATALENGTH(@S) AS [Chars In @S];';
-- PRINT @SQL; -- for debug
-- SET @S = (@A+@A) + (@A + @A...) + ...
EXECUTE (@SQL);
Los valores máximos (para mí) ahora son usar 42
para el primero REPLICATE
, usando 43 variables por grupo, y luego usar 762
para el segundo REPLICATE
, usando 762 grupos de 43 variables cada uno. El grupo inicial está codificado con dos variables.
El resultado ahora muestra que hay 32.768 caracteres en la @S
variable. Si actualizo el grupo inicial para que sea en (@A+@A+@A)
lugar de solo (@A+@A)
, entonces aparece el siguiente error:
Mensaje 8632, Nivel 17, Estado 2, Línea XXXXX
Error interno: se ha alcanzado un límite de servicios de expresión. Busque expresiones potencialmente complejas en su consulta e intente simplificarlas.
Tenga en cuenta que el número de error es diferente al anterior. Ahora es: 8632 . Y, tengo este mismo límite si uso mi instancia de SQL Server 2012 o la instancia de SQL Server 2017.
Probablemente no sea coincidencia que el límite superior aquí, 32.768 , sea la capacidad máxima de SMALLINT
( Int16
en .NET) IF a partir de 0
(el valor máximo es 32.767, pero las matrices en muchos / la mayoría de los lenguajes de programación están basadas en 0).