Sql server varchar(max)变量的最大大小
在过去的任何时候,如果有人问我一个Sql server varchar(max)变量的最大大小,sql-server,tsql,Sql Server,Tsql,在过去的任何时候,如果有人问我一个varchar(max)的最大大小,我会说2GB,或者查一个更精确的(2^31-1,或2147483647) 然而,在最近的一些测试中,我发现varchar(max)变量显然可以超过这个大小: create table T ( Val1 varchar(max) not null ) go declare @KMsg varchar(max) = REPLICATE('a',1024); declare @MMsg varchar(max) = REPL
varchar(max)
的最大大小,我会说2GB,或者查一个更精确的(2^31-1,或2147483647)
然而,在最近的一些测试中,我发现varchar(max)
变量显然可以超过这个大小:
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
结果:
(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)
因此,鉴于我现在知道一个变量可以超过2GB的界限,有人知道varchar(max)
变量的实际极限是多少吗
(以上测试是在SQL Server 2008(不是R2)上完成的。我想知道它是否适用于其他版本)EDIT:经过进一步调查,我最初认为这是
declare@var datatype=value
语法的异常(bug?)是不正确的
我修改了您2005年的脚本,因为该语法不受支持,然后在2008年尝试了修改后的版本。2005年,我收到试图将LOB扩展到2147483647字节的最大允许大小之外。
错误消息。2008年,修改后的脚本仍然成功
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)
据我所知,2008年没有上限 在SQL Server 2005中,问题中的代码在分配给
@GGMMsg
变量时失败
正在尝试将LOB增长到超出允许的最大大小2147483647
字节
下面的代码在以下情况下失败:
复制:结果的长度超过的长度限制(2GB)
目标类型为大型
然而,这些限制似乎已悄然解除。2008年
DECLARE @y VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),92681);
SET @y = REPLICATE(@y,92681);
SELECT LEN(@y)
返回
8589767761
我在我的32位台式机上运行了这个,所以这个8GB的字符串远远超出了可寻址内存
运行
select internal_objects_alloc_page_count
from sys.dm_db_task_space_usage
WHERE session_id = @@spid
返回
internal_objects_alloc_page_co
------------------------------
2144456
因此,我假设这一切只是存储在tempdb
的LOB
页面中,没有验证长度。页面计数的增长都与SET@y=REPLICATE(@y,92681)有关代码>语句。对@y
的初始变量赋值和LEN
计算没有增加这一点
之所以提到这一点,是因为页面数量远远超过了我的预期。假设一个8KB的页面,那么它的计算结果是16.36GB,这显然是看起来需要的两倍。我推测这可能是因为字符串连接操作效率低下,需要复制整个巨大的字符串并在末尾追加一个块,而不能添加到现有字符串的末尾。不幸的是,目前varchar(max)变量的.WRITE
方法
添加
我还测试了连接nvarchar(max)+nvarchar(max)
和nvarchar(max)+varchar(max)
的行为。这两者都允许超过2GB限制。然后尝试将此结果存储在表中,但失败,错误消息为尝试将LOB增长到2147483647字节的最大允许大小之外。
再次。脚本如下(可能需要很长时间才能运行)
声明@x varchar(max)='XX';SELECT LEN(REPLICATE(@x,2147483647))
为我提供了4294967294
,但运行时间很长-即使在SELECT
返回后,也不确定额外的时间花在了什么上。脚本总是产生错误(通过尝试插入表),但在2008年,我总是在第一个结果集中得到一个结果,表示变量确实存在,并且长度超过2^31-1。@Damien_the_unsiever:我将脚本缩减为变量部分,现在得到与您相同的结果。2005年,我在set@GGMMsg=…
语句中遇到了尝试增长…
错误。在2008年,脚本成功了。非常好-因此文档似乎相当“不完整”-我注意到通常的页面引用了最大“存储大小”,这可能只适用于列,而不适用于变量。@Damien-显然是这样的。不确定在总页数方面是否还有其他限制,但我认为它存储在B树结构中(基于SQL Server 2008内部的p.381),因此原则上可以明确扩展。@Damien_不相信者-根据这里的实验,似乎完全错了,相当明确地指出“大型对象(LOB)数据类型变量和参数。。。类型的大小最多可达2 GB“有点没用,但很有趣。理论上,您可以用一个变量填充磁盘…:-)我在这里有些犹豫,因为在变量中存储值与在列中存储值不同。你想用一个专栏来代替它吗?或者你有更新吗?即使是SQL Server 2000在代码中的文字字符串中也可能有长度超过8000个字符的varchar
值,只要您不尝试将其放入变量或varchar
列中。
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