Sql server中内部函数fn_PhysLocFormatter存在解析错误详解

前言

有网友指出,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

SiteID


%%physloc%%


sys.fn_PhysLocFormatter(%%physloc%%)


1


0xE900000001000000


(1:59648:0)


23


0xE900000001000100


(1:59648:1)


24


0xE900000001000200


(1:59648:2)


......


149


0xE900000001007F00


(1:59648:127)


150


0xE900000001008000


(1:59648:128)


151


0xE900000001008100


(1:59648:33024)


152


0xE900000001008200


(1:59648:33280)


......


226


0xE90000000100CC00


(1:59648:52224)


227


0xE90000000100CD00


(1:59648:52480)


228


0x4B02000001000000


(1:587:0)


229


0x4B02000001000100


(1:587:1)


......


360


0x4B02000001007F00


(1:587:127)


361


0x4B02000001008000


(1:587:128)


362


0x4B02000001008100


(1:587:33024)


363


0x4B02000001008200


(1:587:33280)


......


422


0x4B0200000100BD00


(1:587:48384)


423


0x4B0200000100BE00


(1:587:48640)


424


0x3C05000001000000


(1:1340:0)


425


0x3C05000001000100


(1:1340:1)


......


552


0x3C05000001008000


(1:1340:128)


553


0x3C05000001008100


(1:1340:33024)


596


0x3C0500000100AC00


(1:1340:44032)


597


0x9978000001000000


(1:39288:0)


......


658


0x9978000001003D00


(1:39288:61)

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

dbcc ind(wjgk,nt_siteinfo,0)

PagePID


IAMFID


IAMPID


PageType


IndexLevel


NextPagePID


PrevPagePID


238


NULL


NULL


10


NULL


0


0


233


1


238


1


0


587


0


587


1


238


1


0


1340


233


1340


1


238


1


0


30873


587


30873


1


238


1


0


0


1340

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), reverse (substring (@physical_locator, 5, 2)))
 select @slot_id = convert (binary (2), reverse (substring (@physical_locator, 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之间的字节时,被认为是双字节字符而组合在一起参与反转操作,造成了错误。

总结

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

(0)

相关推荐

  • Sql server中内部函数fn_PhysLocFormatter存在解析错误详解

    前言 有网友指出,SQL Server 2012中fn_PhysLocFormatter内部函数在解析数据行记录位置时存在错误,见:http://www.itpub.net/thread-1751655-1-1.html,实际测试后发现,一是2008R2中同样存在问题,二是不仅页号解析存在问题,槽号解析也存在同样问题. 下面先查看表NT_SiteInfo的数据行记录位置. select SiteID,%%physloc%%,sys.fn_PhysLocFormatter(%%physloc%%)

  • SQL Server中identity(自增)的用法详解

    一.identity的基本用法 1.含义 identity表示该字段的值会自动更新,不需要我们维护,通常情况下我们不可以直接给identity修饰的字符赋值,否则编译时会报错 2.语法 列名 数据类型 约束 identity(m,n) m表示的是初始值,n表示的是每次自动增加的值 如果m和n的值都没有指定,默认为(1,1) 要么同时指定m和n的值,要么m和n都不指定,不能只写其中一个值,不然会出错 3.实例演示 不指定m和n的值 create table student1 ( sid int p

  • SQL Server中row_number分页查询的用法详解

    ROW_NUMBER()函数将针对SELECT语句返回的每一行,从1开始编号,赋予其连续的编号.在查询时应用了一个排序标准后,只有通过编号才能够保证其顺序是一致的,当使用ROW_NUMBER函数时,也需要专门一列用于预先排序以便于进行编号. ROW_NUMBER() 说明:返回结果集分区内行的序列号,每个分区的第一行从1开始. 语法:ROW_NUMBER () OVER ([ <partition_by_clause> ] <order_by_clause>) . 备注:ORDER

  • SQL Server中的排名函数与分析函数详解

    一.排名开窗函数概述 SQL Server的排名函数是对查询的结果进行排名和分组,TSQL共有4个排名函数,分别是:ROW_NUMBER.RANK.DENSE_RANK和NTILE. 他们和OVER()函数搭配使用,按照特定的顺序排名. 排名开窗函数可以单独使用ORDER BY 语句,也可以和PARTITION BY同时使用. PARTITION BY用于将结果集进行分组,开窗函数应用于每一组. ODER BY 指定排名开窗函数的顺序.在排名开窗函数中必须使用ORDER BY语句. 1.ROW_

  • SQL Server中日期时间函数的用法详解

    1.getdate():获取当前日期 返回当前SQLServer服务器所在计算机的日期和时间.返回值舍入到最近的秒小数部分,精度为.333秒数据库十七偏移量不包含在内. select getdate() --输出 2013-03-09 15:16:00.570 2.getutcdate():获取UTC时间值 select GETUTCDATE() -- 2013-06-18 08:02:53.253 3.year():获取年度信息 year函数以int数据类型的格式返回特定日期的年度信息.其中的

  • Sql Server 开窗函数Over()的使用实例详解

    利用over(),将统计信息计算出来,然后直接筛选结果集 declare @t table( ProductID int, ProductName varchar(20), ProductType varchar(20), Price int) insert @t select 1,'name1','P1',3 union all select 2,'name2','P1',5 union all select 3,'name3','P2',4 union all select 4,'name4

  • SQL Server修改数据的几种语句详解

    目录 一:INSERT语句 二:INSERT INTO SELECT语句 三:UPDATE语句 四:DELETE语句 总结 本篇主要讲解的是SQL Server 中修改数据的几种语句: INSERT语句 INSERT INTO SELECT语句 UPDATE语句 DELETE语句 一:INSERT语句 INSERT语句向表中添加新行,以下是INSERT语句的最基本形式: 首先:table_name指定要插入的表的名称: 其次,column_list指定要在其中插入数据的一个或多个列的列表.必须将

  • SQL server分页的四种方法思路详解(最全面教程)

    目录 方法一:三重循环 思路 方法二:利用max(主键) 方法三:利用row_number关键字 第四种方法:offset /fetch next(2012版本及以上才有) 总结   这篇博客讲的是SQL server的分页方法,用的SQL server 2012版本.下面都用pageIndex表示页数,pageSize表示一页包含的记录.并且下面涉及到具体例子的,设定查询第2页,每页含10条记录.   首先说一下SQL server的分页与MySQL的分页的不同,mysql的分页直接是用lim

  • sql – Oracle中匿名TABLE/VARRAY类型示例详解

    前言 本文主要介绍的是关于sql Oracle匿名TABLE/VARRAY类型的相关内容,在Oracle中,我有时会创建一些这样的结构 SELECT * FROM TABLE(STRINGS('a', 'b', 'c')) SELECT * FROM TABLE(NUMBERS(1, 2, 3)) 显然,我可以为上述声明我自己的类型.我可以在TABLE和VARRAY之间进行选择.例如: CREATE TYPE STRINGS AS TABLE OF VARCHAR2(100); CREATE T

  • Spring中自定义Schema如何解析生效详解

    前言 随着 Spring Boot 的日渐流行,应用里的大部分配置都被隐藏了起来,我们仅需要关心真正的业务内容, Controller, Service, Repository,拿起键盘就是一通业务代码的Coding,具体的 Component Scan,View,PlaceHolder ... 都可以抛在脑后.但其实这种零配置在 Java 应用开发中,还真不太久. 「由奢入俭难」,不少开发者都经历过 Spring XML 配置的冗长,再回到这种配置确实不好受. 但有些时候,由于配置的内容在 S

随机推荐