加入收藏 | 设为首页 | 会员中心 | 我要投稿 衡阳站长网 (https://www.0734zz.cn/)- 数据集成、设备管理、备份、数据加密、智能搜索!
当前位置: 首页 > 创业 > 经验 > 正文

Sql server中内部函数fn

发布时间:2020-12-24 08:35:39 所属栏目:经验 来源:网络整理
导读:前言 有网友指出,SQL Server 2012中fn_PhysLocFormatter内部函数在解析数据行记录位置时存在错误,见:http://www.itpub.net/thread-1751655-1-1.html,实际测试后发现,一是2008R2中同样存在问题,二是不仅页号解析存在问题,槽号解析也存在同样问题。 下

前言

有网友指出,SQL Server 2012中fn_PhysLocFormatter内部函数在解析数据行记录位置时存在错误,见:http://www.itpub.net/thread-1751655-1-1.html,实际测试后发现,一是2008R2中同样存在问题,二是不仅页号解析存在问题,槽号解析也存在同样问题。

下面先查看表NT_SiteInfo的数据行记录位置。

select SiteID,%%physloc%%,sys.fn_PhysLocFormatter(%%physloc%%) from NT_SiteInfo

下面查看表NT_SiteInfo分配的数据页情况。

dbcc ind(wjgk,nt_siteinfo,0)

Microsoft未公开的伪列%%physloc%%,类型为Binary(8),返回表中记录的RowID,格式是:前4字节表示页号,中间2字节表示文件号,最后2字节表示槽号。

对照上面的实际数据,可以发现sys.fn_PhysLocFormatter在解析记录位置时,既有采用高字节在前的BIG_ENDIAN格式,又有采用低字节在前的LITTLE_ENDIAN格式,造成采用高字节在前的BIG_ENDIAN格式解析的数据错误:

页号解析:
E9000000解析为59648(E900),错误,实际应为233(E9)

4B020000解析为576(24B),正确

3C050000解析为1340(53C),正确

99780000解析为39288(9978),错误,实际应为30873(7899)

槽号解析:

8000解析为128(0080),正确

8100解析为33024(8100),错误,应为129(0081)

下面给出错误原因。

先看下sys.fn_PhysLocFormatter函数的定义:

select OBJECT_DEFINITION(object_id('sys.fn_PhysLocFormatter'))
go
 
-------------------------------------------------------------------------------
-- Name: sys.fn_PhysLocFormatter
--
-- Description:
-- Formats the output of %%physloc%% virtual column
--
-- Notes:
-------------------------------------------------------------------------------
create function sys.fn_PhysLocFormatter (@physical_locator binary (8))
 returns varchar (128)
as
 begin
 declare @page_id binary (4)
 declare @file_id binary (2)
 declare @slot_id binary (2)
 -- Page ID is the first four bytes,then 2 bytes of page ID,then 2 bytes of slot
 --
 select @page_id = convert (binary (4),reverse (substring (@physical_locator,1,4)))
 select @file_id = convert (binary (2),5,2)))
 select @slot_id = convert (binary (2),7,2)))
 return '(' + cast (cast (@file_id as int) as varchar) + ':'
 + cast (cast (@page_id as int) as varchar) + ':'
 + cast (cast (@slot_id as int) as varchar) + ')'
 end

再看下reverse函数:

select reverse('工人')
----
人工
 
(1 行受影响)
 
select reverse('12345工人')
---------
人工54321
 
(1 行受影响)
 
select reverse('工12345人')
---------
人54321工
 
(1 行受影响)

结论:问题出在reverse函数上。

reverse函数的作用是字符反转,而不是字节反转,当遇到81-FE之间的字节时,被认为是双字节字符而组合在一起参与反转操作,造成了错误。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程小技巧的支持。

(编辑:衡阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读