昨天一个同事突然问我,说他在SQL 2000数据库创建如下表的时候,突然碰到了下面一条警告信息。SQL脚本和警告信息如下:

IF OBJECT_ID(N'Log') IS  NULL

BEGIN
CREATE TABLE Log
(
    [Date]         DATETIME,
    [Thread]       NVARCHAR(255),
    [Level]        NVARCHAR(50),
    [Logger]       NVARCHAR(255),
    [Message]      NVARCHAR(4000),
    [Exception]    NVARCHAR(4000)
    
)
END
ELSE
  PRINT('该表已经存在,请检查数据库');
GO

Warning: The table 'Log' has been created but its maximum row size (17159) exceeds the maximum number of bytes per row (8060). INSERT or UPDATE of a row in this table will fail if the resulting row length exceeds 8060 bytes.

我以前也没有遇见过这样的警告信息,当时我在SQL SERVER 2000 下面执行这段脚本,果然有这个警告信息,还有就是为什么Maximun ROW SIZE 是17159?;当我在SQL SERVER 2005 下面执行这段脚本却没有警告信息出现,难道SQL SERVER 2005 与SQL SERVER 2000在存贮机制上面有什么不同?在搞清楚这些问题前,我们先来看看其它的一些相关问题,就是SQL SERVER 2000/2005中最大数据行都是8060字节(对定长数据而言), 其中SQL SERVER 2000中可以使用的大小为8039字节, 而SQL SERVER 2005可以使用的大小为8053字节。我们可以从下面的脚本中实验一下(SQL SERVER 2005)

CREATE TABLE TEST
(
    FIELD1 CHAR(4000),
    FIELD2 CHAR(4000),
    FIELD3 CHAR(53)
)

CREATE TABLE TEST1
(
    FIELD1 CHAR(4000),
    FIELD2 CHAR(4000),
    FIELD3 CHAR(54)

最小行大小8061 = 4000 + 4000 + 54 + 7(内部开销)。下面我们改变下上面脚本的数据类型,如下所示,看看在SQL SERVER 2005下的情况

IF OBJECT_ID(N'Log') IS  NULL
BEGIN
CREATE TABLE Log
(
    [Date]             DATETIME,
    [Thread]           CHAR(255),
    [Level]            CHAR(50),
    [Logger]           CHAR(255),
    [Message]          CHAR(4000),
    [Exception]        CHAR(4000)
    
)
END
ELSE
  PRINT('该表已经存在,请检查数据库');

GO

那么最小行8575是怎么算出来的呢,我们先看这张经典数据行结构图(引自Inside SQL SERVER)

其实就是8 + 255 + 50 + 255 + 4000 + 4000 = 8568   + 7 = 8575  其中的7个字节是这样来的

Status Bits A                      1

Status Bits B                       1

Length of fixed-length ........               2

number of columns 2

Null bitmap 1 bit for each column         (6/8)1

由于表里面没有变长字段,所以其它与变长相关的字节为0 所以为7。 那么接下来我们看看开篇的问题为什么 maximum row size (17159),

8 + 255* 2 + 50 * 2 + 255 * 2 + 4000 * 2 + 4000 *2   = 17128

1 + 1 + 2 + 2 + 1 + 2 + 2* 5  = 19 

那么17128 + 19 =  17147 但是结果是17159,有点不明,查了很多资料也没搞清楚,这个17159 是怎么算出来的,呵呵,希望高手来解答!

呵呵,感谢邀月老大的解答:本来我怎么也找不出的12个字节即是: Heap中非聚集索引的叶级页有一个索引键列值(本例中由系统自动添加),加上一实际数据行的RID,即4+8=12

SELECT t.name AS [Table Name], i.name AS [Index Name], i.minlen as minlen

FROM sysobjects AS t JOIN sysindexes AS i ON t.id = i.id

WHERE t.id > 100  AND t.id=object_id( 'log')

SQL SERVER 表最小行的一个纠结问题的更多相关文章

  1. SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database)

    原文:SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database) 一.本文所涉及的内容(Contents) 本文所涉及的内容(C ...

  2. VFP 用 SPT 来发布一条 SELECT 到一个新的 SQL Server 表

    为了发布一条 SQL SELECT 语句来创建一个新的 SQL Server 表,  SQL Server 数据库的 select into/bulkcopy 选项必须是可用的. 在默认情况下, 对于 ...

  3. sql server 表索引碎片处理

    DBCC SHOWCONTIG (Transact-SQL) SQL Server 2005 其他版本 更新日期: 2007 年 9 月 15 日 显示指定的表或视图的数据和索引的碎片信息. 重要提示 ...

  4. 在一个SQL Server表中的多个列找出最大值

    在一个SQL Server表中一行的多个列找出最大值 有时候我们需要从多个相同的列里(这些列的数据类型相同)找出最大的那个值,并显示 这里给出一个例子 IF (OBJECT_ID('tempdb..# ...

  5. SQL Server表分区的NULL值问题

    SQL Server表分区的NULL值问题 SQL Server表分区只支持range分区这一种类型,但是本人觉得已经够用了 虽然MySQL支持四种分区类型:RANGE分区.LIST分区.HASH分区 ...

  6. SQL Server 表变量和临时表的区别

    SQL Server 表变量和临时表的区别 一.表变量 表变量在SQL Server 2000中首次被引入.表变量的具体定义包括列定义,列名,数据类型和约束.而在表变量中可以使用的约束包括主键约束,唯 ...

  7. SQL Server表分区【转】

    转自:http://www.cnblogs.com/knowledgesea/p/3696912.html SQL Server表分区   什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在 ...

  8. SQL Server表分区详解

    原文:SQL Server表分区详解 什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆 ...

  9. SQL Server 表的管理_关于完整性约束的详解(案例代码)

    SQL Server 表的管理之_关于完整性约束的详解 一.概述: ●约束是SQL Server提供的自动保持数据库完整性的一种方法, 它通过限制字段中数据.记录中数据和表之间的数据来保证数据的完整性 ...

随机推荐

  1. Kylin与CDH兼容性剖析

    1. 概述 Apache Kylin™是一个开源的分布式分析引擎,提供Hadoop之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据,最初由eBay Inc. 开发并贡献至开源社区.它能 ...

  2. JavaScript(四)操作符

      6种表达式 原始表达是  初始化表达式 函数定义表达式 函数调用表达式 属性访问表达式 对象创建表达式 操作符 操作符的优先级 属性访问[] .  >  一元操作符 >  */ > ...

  3. Java关于BufferedWriter.newline()换行的注意事项

    最近项目中需要导出文件,其实导出文件是一个挺简单的事情.但是却遇到了很奇怪的问题. 首先导出到文件需要用到 BufferedWriter.而换行则是通过 bw.newline() 方法,问题将出在 n ...

  4. Redis随笔(二)redis desktop manager 安装并且连接redis服务器

    1.首先在win10下安装redis desktop manager 2.查看虚拟机防火墙状态,启动状态,则关闭掉 查看防火墙状态: systemctl status firewalld.servic ...

  5. 如何在linux下录制terminal操作?

    相关包: ttyrec: ttyrec is a tty recorder. Recorded data can be played back with the included ttyplay co ...

  6. JavaScript获取当前url路径

    1.假设当前页完整地址是:http://localhost:61768/Home/Index?id=2 //获取当前窗口的Url var url = window.location.href; //结 ...

  7. 使用Anaconda搭建TensorFlow-GPU环境

    前言: 对于深度学习来说,各种框架torch,caffe,keras,mxnet,tensorflow,pandapanda环境要求各一,如果我们在一台服务器上部署了较多的这样的框架,那么各种莫名的冲 ...

  8. 使用mysql悲观锁解决并发问题

    最近学习了一下数据库的悲观锁和乐观锁,根据自己的理解和网上参考资料总结如下: 悲观锁介绍(百科): 悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持 ...

  9. NOI2017&&codeM2017游记

    7.17 坐了一天动车到绍兴,宿舍环境什么的还是很棒的. 7.18 早上开幕式,没啥好看的,例行节目+讲话. 下午笔试,顺利满分,不过ccz挂了一道多选,99分,影响应该不是很大. 练习赛出人意料地没 ...

  10. “玲珑杯”ACM比赛 Round #19题解&源码【A,规律,B,二分,C,牛顿迭代法,D,平衡树,E,概率dp】

    A -- simple math problem Time Limit:2s Memory Limit:128MByte Submissions:1599Solved:270 SAMPLE INPUT ...