USE MyTestDB
GO
CREATETABLE t6 (a char(8000), b CHAR(54))INSERTINTO t6 VALUES(REPLICATE('a',8000), REPLICATE('b',53))
1.
2.
3.
4.
5.
从错误信息中可以清楚的看到,我的行记录总大小是 8061, 超过了系统规定的行记录大小8060。
接下来我们验证下 数据页 最小的保留大小是不是 34byte ?找到表数据页即可。
USE MyTestDB
GO
CREATETABLE t6 (a char(8000), b CHAR(53))INSERTINTO t6 VALUES(REPLICATE('a',8000), REPLICATE('b',53))SELECT*FROM dbo.t6;
DBCC TRACEON(3604)
DBCC IND(MyTestDB,t6,-1)
其实从上面的分析中可以得出,数据页还是有 34byte 的保留空间的,可能是出于某些原因不想再塞了,当然也可以用 WinDbg 观察下源码逻辑,可以下一个 C++ 异常断点。
0:113> sxe eh
0:113> g
(6aec.6a20): C++ EH exception - code e06d7363 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
KERNELBASE!RaiseException+0x69:00007ff8`f61b3e49 0f1f440000 nop dword ptr [rax+rax]0:020> k
# Child-SP RetAddr Call Site
0000000022`cddf7b80 00007ff8`dd2f6720 KERNELBASE!RaiseException+0x690100000022`cddf7c60 00007ff8`bab85763 VCRUNTIME140!_CxxThrowException+0x90[D:\a\_work\1\s\src\vctools\crt\vcruntime\src\eh\throw.cpp @ 75]0200000022`cddf7cc0 00007ff8`bab85339 sqldk!TurnUnwindAndThrowImpl+0x5820300000022`cddf81b0 00007ff8`bab8531b sqldk!SOS_OS::TurnUnwindAndThrow+0x90400000022`cddf81e0 00007ff8`bab84fca sqldk!ex_raise2+0x56e0500000022`cddf8520 00007ff8`5cf2c056 sqldk!ex_raise+0xc30600000022`cddf85a0 00007ff8`5cf2e54d sqlmin!RaiseHoBtRowsizeError+0x1560700000022`cddf8600 00007ff8`5c33ac06 sqlmin!SECreateRowset+0x4440800000022`cddfa940 00007ff8`995632f8 sqlmin!DDLAgent::SECreateRowsets+0x2e0
...