En cualquier momento en el pasado, si alguien me hubiera preguntado el tamaño máximo de a varchar(max)
, habría dicho 2GB, o habría buscado una cifra más exacta (2 ^ 31-1, o 2147483647).
Sin embargo, en algunas pruebas recientes, descubrí que las varchar(max)
variables aparentemente pueden exceder este tamaño:
create table T (
Val1 varchar(max) not null
)
go
declare @KMsg varchar(max) = REPLICATE('a',1024);
declare @MMsg varchar(max) = REPLICATE(@KMsg,1024);
declare @GMsg varchar(max) = REPLICATE(@MMsg,1024);
declare @GGMMsg varchar(max) = @GMsg + @GMsg + @MMsg;
select LEN(@GGMMsg)
insert into T(Val1) select @GGMMsg
select LEN(Val1) from T
Resultados:
(no column name)
2148532224
(1 row(s) affected)
Msg 7119, Level 16, State 1, Line 6
Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes.
The statement has been terminated.
(no column name)
(0 row(s) affected)
Entonces, dado que ahora sé que una variable puede superar la barrera de los 2GB, ¿alguien sabe cuál es el límite real para una varchar(max)
variable?
(La prueba anterior se completó en SQL Server 2008 (no R2). Me interesaría saber si se aplica a otras versiones)
sql-server
tsql
Damien_The_Unbeliever
fuente
fuente
declare @x varchar(max) = 'XX'; SELECT LEN(REPLICATE(@x,2147483647))
da4294967294
para mí, pero tarda mucho en ejecutarse, incluso después de queSELECT
ha regresado, por lo que no estoy seguro de qué dedica ese tiempo extra.Respuestas:
Por lo que puedo decir, no hay límite superior en 2008.
En SQL Server 2005, el código de su pregunta falla en la asignación a la
@GGMMsg
variable conel siguiente código falla con
Sin embargo, parece que estas limitaciones se han eliminado silenciosamente. En 2008
DECLARE @y VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),92681); SET @y = REPLICATE(@y,92681); SELECT LEN(@y)
Devoluciones
Ejecuté esto en mi máquina de escritorio de 32 bits, por lo que esta cadena de 8 GB excede la memoria direccionable
Corriendo
select internal_objects_alloc_page_count from sys.dm_db_task_space_usage WHERE session_id = @@spid
Devuelto
internal_objects_alloc_page_co ------------------------------ 2144456
así que supongo que todo esto simplemente se almacena en
LOB
páginastempdb
sin validación de longitud. El crecimiento del recuento de páginas estuvo asociado con laSET @y = REPLICATE(@y,92681);
declaración. La asignación de variable inicial ay@y
elLEN
cálculo no aumentó esto.La razón para mencionar esto es porque el recuento de páginas es mucho más de lo que esperaba. Suponiendo una página de 8 KB, esto da como resultado 16,36 GB, que obviamente es más o menos el doble de lo que parecería ser necesario. Especulo que esto se debe probablemente a la ineficacia de la operación de concatenación de cadenas que necesita copiar toda la cadena enorme y agregar un fragmento al final en lugar de poder agregar al final de la cadena existente. Desafortunadamente, por el momento, el
.WRITE
método no es compatible con variables varchar (max).Adición
También probé el comportamiento con concatenación
nvarchar(max) + nvarchar(max)
ynvarchar(max) + varchar(max)
. Ambos permiten superar el límite de 2 GB. Intentar almacenar los resultados de esto en una tabla y luego falla, sin embargo, con el mensaje de errorAttempting to grow LOB beyond maximum allowed size of 2147483647 bytes.
nuevamente. El script para eso se encuentra a continuación (puede tardar mucho en ejecutarse).DECLARE @y1 VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),2147483647); SET @y1 = @y1 + @y1; SELECT LEN(@y1), DATALENGTH(@y1) /*4294967294, 4294967292*/ DECLARE @y2 NVARCHAR(MAX) = REPLICATE(CAST('X' AS NVARCHAR(MAX)),1073741823); SET @y2 = @y2 + @y2; SELECT LEN(@y2), DATALENGTH(@y2) /*2147483646, 4294967292*/ DECLARE @y3 NVARCHAR(MAX) = @y2 + @y1 SELECT LEN(@y3), DATALENGTH(@y3) /*6442450940, 12884901880*/ /*This attempt fails*/ SELECT @y1 y1, @y2 y2, @y3 y3 INTO Test
fuente
varchar
valores de más de 8000 caracteres en cadenas literales en el código, siempre que no intente ponerlo en una variable ovarchar
columna.EDITAR : Después de una mayor investigación, mi suposición original de que se trataba de una anomalía (¿error?) De la
declare @var datatype = value
sintaxis es incorrecta.Modifiqué su script para 2005 ya que esa sintaxis no es compatible, luego probé la versión modificada en 2008. En 2005, aparece el
Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes.
mensaje de error. En 2008, la secuencia de comandos modificada todavía tiene éxito.declare @KMsg varchar(max); set @KMsg = REPLICATE('a',1024); declare @MMsg varchar(max); set @MMsg = REPLICATE(@KMsg,1024); declare @GMsg varchar(max); set @GMsg = REPLICATE(@MMsg,1024); declare @GGMMsg varchar(max); set @GGMMsg = @GMsg + @GMsg + @MMsg; select LEN(@GGMMsg)
fuente
Attempting to grow...
error en laset @GGMMsg=...
declaración. En 2008, el guión tiene éxito.