日期:2014-05-18  浏览次数:20606 次

一个更新引发的问题的思考的思考,求助各位了.
做如下更新时,
UPDATE t
SET col= 'Stokke KEEP Complete-Cherry'
where ... -- 符合条件的只有一笔记录.

Msg 511, Level 16, State 1, Procedure xxx, Line 170
Cannot create a row of size 8062 which is greater than the allowable maximum row size of 8060.

查该t.col字段数据类型为varchar(500),且表中所有字段长度总和亦远小于8060,
后跟User联系确认该表曾有个xml字段,后来删除了. 
估计是空间分配未回收问题(仅是估计),做表索引重建,问题解决.
DBCC DBREINDEX('t', '', 90)

请问哪位可以解释及重现这个错误?

------解决方案--------------------
等牛人来解释和重现。
------解决方案--------------------
SQL SERVER 2005下测试。
SQL code

if object_id('ta') is not null
drop table ta
go
create table ta(id int identity primary key, col1 char(8000), col2 char(40), col3 varchar(20))
go
insert into ta
values('col1', 'col2', '12')
go
select * from ta
go
update ta
set col3='1234567890'
go
select * from ta
go
alter table ta
drop column col1
go
select * from ta
go
update ta
set col3='1234567890'
go
dbcc dbreindex('ta', '', 90)
go
update ta
set col3='1234567890'
go
select * from ta
go

------解决方案--------------------
实际上这里的问题应该追加为“为了已经drop column,但行数据限制仍存在”的问题。

并非某个数据类型的限制,因为是先有了错误,才有了这些重现语句。

当然避免和处理的方法很简单,大家在做分区数据时都有体会,数据不会随着意愿而移动,即使做了分区函数和方案仍要通过索引来迁移数据到相应的位置。

通过前后对比时,在图2中我们可以发现数据页已经记录了drop column的存在,但数据没有转移,仍需要在该区中继续存储数据,那么除非重新给它分配IAM链。

图1


图2


图3

------解决方案--------------------
这个以前关注过,印象中存储引擎那本书也有说,石头哥也做过博文
http://blog.csdn.net/happyflystone/article/details/4923803