2011-09-02 67 views
4

是否有一种干净的方式来确定表中的行大小,然后再向其中添加新的列并且不超过8060字节限制?例如,如果表行长度当前为8055字节,并且我想添加日期时间(8个字节),则这将会越过,因为它将变为8063个字节(不包括空映射)。但是,如果我添加一个整数(4个字节),这会给它8059个字节,这符合表大小(不包括空映射)。SQL Server 2005 - 到达表​​行大小限制

我目前能够获得表的大小,但是我发现很难创建一个SQL函数来获取数据类型的大小(int,datetime等)以及数据类型是否需要额外的字节映射。

是否有一个函数我可以使用/开发接受两个变量:tablename和datatype:fnIsEnoughStorage('table1',int)并从标量函数返回一个布尔值(是/否)。

如果为true,我将在测试确定后继续执行ALTER TABLE命令。

+5

如果我的一张桌子有超过8k的限制,我会认真看待设计。 –

+0

你是否真的通过找出你可以添加到哪些数据类型来设计你的表格,而不是通过分析需要存储哪些数据? –

回答

5

该查询这里将确定哪些表potentitally危险的,有可能的最大行大小将超过现有的8060个字节:

;WITH TableRowSizes AS 
(
    SELECT 
     t.NAME 'TableName', 
     COUNT(1) 'NumberOfColumns', 
     SUM (c.max_length) 'MaxRowLength' 
    FROM 
     sys.columns c 
    INNER JOIN 
     sys.tables t ON c.object_id = t.object_id 
    WHERE 
     c.user_type_id NOT IN (98, 165, 167, 231) -- sql_variant, varbinary, varchar, nvarchar 
    GROUP BY 
     t.name 
) 
SELECT * 
FROM TableRowSizes 
WHERE MaxRowLength > 8060 
ORDER BY MaxRowLength DESC 

你行实际使用超过8060字节,这并不意味着 - 它只是总结ea可能的最大尺寸ch栏。

如果你想确定实际当前使用的大小,你也许可以做到通过检查DATALENGTH(colname)功能(而不是使用从sys.columns理论最大值)类似

更新:添加一个WHERE子句我的CTE SELECT基于gbn的响应 - 这些类型不应该用于确定该行是否可能打破8060字节的大小限制。

+0

需要为每个可变长度添加2个+ null位图+可能是rowversioning指针。否则这将是误导。 – gbn

+0

@gbn:是的,我知道 - 但是很快就会变得非常混乱 - 现在这只是一个近似值,但通常足够接近。 –

+0

谢谢,最好的方法可能是最实用的方法。我相信最优雅的方法是测试我在表中留下了多少空间,并说明它是否少于32字节,防止添加列。 – Resurface

3

行可以打破8060字节限制,因为varchar/nvarchar列可以使用overflow

你会得到一个警告,但它是允许的。

如果打破固定长度的列的8060字节限制,则必须垂直分区(例如1:1表)。

请注意,您的新INT列不走“底”:在磁盘上的结构被很好地定义和数据将被移动,以适应新的固定长度字段:OneTwo

+0

我需要在这种情况下适应我的脚本.....有没有办法找出表中的哪些列是“可溢出的”?我似乎无法在'sys.columns'或'sys.types'中找到该属性的任何指示(我寻找'is_variable'或类似的东西....) –

+0

@marc_s:我知道的唯一方法是从我给的第一个链接:varchar,nvarchar,varbinary,sql_variant – gbn

+0

谢谢!我已更新我的脚本以反映这些附加信息。 –