Sql 数字数据类型-存储
根据数字(10,2)-10类型的数据,表示精度应为9字节 但当我这么做的时候:Sql 数字数据类型-存储,sql,sql-server,Sql,Sql Server,根据数字(10,2)-10类型的数据,表示精度应为9字节 但当我这么做的时候: DECLARE @var as numeric(10,0) = 2147483649 SELECT @var, DATALENGTH(@var) DATALENGTH(@var)返回的是5字节,而不是10字节。有人能解释一下原因吗?文档规定: 最大存储大小因精度而异 对于给定的精度,存储不是恒定的。实际存储取决于该值 值得注意的是,这与整体性无关。下面还返回5: declare @var numberic(11,
DECLARE @var as numeric(10,0) = 2147483649
SELECT @var, DATALENGTH(@var)
DATALENGTH(@var)返回的是5字节,而不是10字节。有人能解释一下原因吗?文档规定: 最大存储大小因精度而异 对于给定的精度,存储不是恒定的。实际存储取决于该值 值得注意的是,这与整体性无关。下面还返回5:
declare @var numberic(11, 1) = 214483649.8
实际上,SQL Server似乎使用了值所需的存储量,而不是类型的最大值。您可以通过将“10”更改为“20”并注意到数据长度没有改变,很容易看到这一点
编辑:
如果运行以下命令,可以看到对值的依赖:
declare @a numeric(20, 1) = '123.1';
declare @b numeric(20, 1) = '1234567890123456789.0';
select datalength(@a), datalength(@b);
这两种长度不相同。文档规定: 最大存储大小因精度而异 对于给定的精度,存储不是恒定的。实际存储取决于该值 值得注意的是,这与整体性无关。下面还返回5:
declare @var numberic(11, 1) = 214483649.8
实际上,SQL Server似乎使用了值所需的存储量,而不是类型的最大值。您可以通过将“10”更改为“20”并注意到数据长度没有改变,很容易看到这一点
编辑:
如果运行以下命令,可以看到对值的依赖:
declare @a numeric(20, 1) = '123.1';
declare @b numeric(20, 1) = '1234567890123456789.0';
select datalength(@a), datalength(@b);
这两个长度不一样。另一个答案是@GordonLinoff的错误,或者至少是误导。
Numeric
不是以可变的字节数存储的,而是以固定的大小存储特定的精度
在SQL Server 2017上尝试此操作会得到与您相同的结果
您最初链接到的文档,例如numeric
,关于存储不同精度的数字所需的字节数是正确的
此存储要求仅基于数值列的精度。换句话说,这就是使用了多少字节的存储空间。它不是取决于该行中的值的最大值。
所有行对该列使用相同的字节数
此变化的关键是DATALENGTH
说明此函数的文档
看来,DATALENGTH
的意思并不像磁盘上的“表示”那样是“表示”,而是内存中的“表示”。
另一篇关于numeric
的文档是关于numeric
的磁盘存储
这可能是因为DATALENGTH
主要用于var*类型或其他BLOB类型
因此,尽管一个数值(20,1)
需要13个字节的存储空间,但根据值的不同,SQL Server可以在内存中以较小的字节数表示它,也就是在DATALENGTH
计算它时
正如我在另一篇评论中指出的,尽管numeric
有不同的大小,但它是一种固定大小的数据类型,因为对于特定表中的特定列,每个值占用相同的存储量
大致上,SQL Server行包含4个部分:
4字节头
固定大小数据
将偏移量转换为可变大小的数据
可变大小数据
数字和其他固定大小类型存储在2中,var*
存储在4中,长度存储在3中
此脚本显示具有某些固定和可变列的表的元数据
declare @a numeric(20, 1) = '123.1';
declare @b numeric(20, 1) = '1234567890123456789.0';
select datalength(@a) union select datalength(@b);
create table #numeric(num1 numeric(20,1), text1 varchar(10), char2 char(6));
insert into #numeric(num1, text1, char2) values ('123.1', 'hello', 'first'), ('1234567890123456789.0', 'there', '2nd');
select datalength(num1) from #numeric;
select
t.name as table_name,
c.name as column_name,
pc.partition_column_id,
pc.max_inrow_length,
pc.max_length,
pc.precision,
pc.scale,
pc.collation_name,
pc.leaf_offset
from tempdb.sys.tables as t
join tempdb.sys.partitions as p
on(t.object_id=p.object_id)
join tempdb.sys.system_internals_partition_columns as pc
on(pc.partition_id=p.partition_id)
join tempdb.sys.columns as c
on((c.object_id=p.object_id)and(c.column_id=pc.partition_column_id))
where (t.object_id=object_id('tempdb..#numeric'));
drop table #numeric;
请注意leaf\u offset
列。这表示值在原始二进制数据中的起始位置。
第一列在4字节头之后立即开始。
根据SQL文档,第二个固定列在13字节之后开始。
varchar
列的偏移量为-1,表示它是一个可变长度的列&它在字节数组中的位置不是固定的。
在这种情况下,它可能是固定的,因为只有一个var列,但是altertable
语句可以添加另一个列&移位
如果您想进一步研究,最好的资料来源是卡伦·德莱尼(Kalen Delaney)的一本名为《SQL Server内部结构》的书。她是编写SQL Server的团队的一员。另一个由@GordonLinoff给出的答案是错误的,或者至少是误导性的。
Numeric
不是以可变的字节数存储的,而是以固定的大小存储特定的精度
在SQL Server 2017上尝试此操作会得到与您相同的结果
您最初链接到的文档,例如numeric
,关于存储不同精度的数字所需的字节数是正确的
此存储要求仅基于数值列的精度。换句话说,这就是使用了多少字节的存储空间。它不是取决于该行中的值的最大值。
所有行对该列使用相同的字节数
此变化的关键是DATALENGTH
说明此函数的文档
看来,DATALENGTH
的意思并不像磁盘上的“表示”那样是“表示”,而是内存中的“表示”。
另一篇关于numeric
的文档是关于numeric
的磁盘存储
这可能是因为DATALENGTH
主要用于var*类型或其他BLOB类型
因此,尽管一个数值(20,1)
需要13个字节的存储空间,但根据值的不同,SQL Server可以在内存中以较小的字节数表示它,也就是在DATALENGTH
计算它时
正如我在另一篇评论中指出的,尽管numeric
有不同的大小,但它是一种固定大小的数据类型,因为对于特定表中的特定列,每个值占用相同的存储量
大致上,SQL Server行包含4个部分:
4字节头
固定大小数据
将偏移量转换为可变大小的数据
可变大小数据
N