做如下更新时,
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)请问哪位可以解释及重现这个错误?
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)请问哪位可以解释及重现这个错误?
你有没有这个库的备份来重现这个问题?
联机文档描述“XML 值以内部格式存储为大型二进制对象 (BLOB)”,所以它不应该占用到8060空间中。"查该t.col字段数据类型为varchar(500),且表中所有字段长度总和亦远小于8060,"或者你生成一个T表的脚本看看。
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
至于为什么重建索引可以,可能就是它触发SQL SERVER真正从数据页中删除该列了。
(可能还存在其他动作也会触发真正的删除吧。)
use dbx;
go
drop table t;
create table t(v nvarchar(4000),v1 nvarchar(4000));
goalter table t add x nvarchar(4000);insert into t select 'aaasdfdsfds','sadfsadfdsf',replicate('x',4000)
select * from t;alter table t drop column x;select * from t;update t set v=REPLICATE('a',4000),v1=REPLICATE('a',4000)
/*
消息 511,级别 16,状态 1,第 1 行
不能创建大小为 8063 的行,该大小大于所允许的最大行大小 8060。
语句已终止。
*/exec sp_spaceused t
char面對以下限制
SQL的行不能跨多頁,且大小限制是8060個字節,頁大小 8192其中頁頭96個字節,頁尾2個字節,還有幾個保留的字節。SQL05以上支持行溢出跨多頁,對部分類型沒有限制如varchar/nvarchar/sql_variant/CLR定義類型等。
如果不重建索引
SELECT a.index_id, name,avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(N'MyJoyDatabase'),OBJECT_ID(N'ta'),NULL,NULL,NULL)AS a
JOIN sys.indexes AS b ON a.object_id=b.object_id AND a.index_id = b.index_id;
没有索引碎片DBCC SHOW_STATISTICS('ta','PK__ta__3213E83F42E1EEFE')也没有索引统计信息难道是页面分配表中没有更新空间使用情况?求解
DBCC PAGE
两个命令就够研究这个内容了
sql规定行数据不能超过一个页也就是8k(8192字节)
系统预留的部分空间,这样最大存储只能是8060字节.针对7#的脚本,把nvarchar类型换成ntext就不存在这个错误了。
图2
图3
楼上牛人啊小弟本想抽空研究下的,还是自己太懒
下面是个人拙见:
这个问题是不是和临时库逐渐增大类似呢?在一个会话中创建的临时表很大,导致临时库tempdb扩充了。当会话结束关掉,临时库的大小还是那么大,虽然里面内容没那么多,必须得手工收缩数据库。
http://blog.csdn.net/happyflystone/article/details/4923803
#13楼 得分:0回复于:2011-11-08 11:10:00SQL code use dbx; go drop table t; create table t(v nvarchar(4000),v1 nvarchar(4000)); go alter table t add x nvarchar(4000); insert into t select 'aaasdfdsfds','sadfsadfdsf',replicate('x',4000) select * from t; alter table t drop column x; select * from t; update t set v=REPLICATE('a',4000),v1=REPLICATE('a',4000) /* 消息 511,级别 16,状态 1,第 1 行不能创建大小为 8063 的行,该大小大于所允许的最大行大小 8060。语句已终止。 */ exec sp_spaceused t
正如9楼所说,删除列时其实并没有从数据页中删除该列。
至于为什么重建索引可以,可能就是它触发SQL SERVER真正从数据页中删除该列了。
(可能还存在其他动作也会触发真正的删除吧。)