在SQL Server中,一般我们都会通过 select * from 表 来查询数据,但有时候,为了探索SQL Server的各种机制,需要看到更原始的数据,或者说是希望从更为底层的方式来看数据,那有没什么办法呢?
其实,通过DBCC PAGE,我们不仅能查看表中的数据,而且还会看到很多内部存储的信息,让你了解SQL Server是如何存储这些数据的。
下面就讲讲如何通过DBCC PAGE来查看表中的数据:
--1.先建表
CREATE TABLE test(idd INT NOT NULL,name VARCHAR(10) NULL)
INSERT INTO TEST
SELECT 1,'abcdefg'
UNION ALL
SELECT 2,'hijklmn'
--SELECT * FROM TEST
SELECT *
FROM sys.tables
WHERE name = 'test'
--2.查询元数据
--hobt_id : 72057594043236352
SELECT hobt_id
FROM sys.partitions
WHERE object_id = object_id('test')
/*
first_page :0x790500000100
拆分成2部分:0100和79050000
这2部分要翻转,也就是0001 和 00000579
前面表示fileId,后面是pageId,都是16机制的表示方法,
通过calc计算器的转换,就是10进制就是1和1401
*/
SELECT first_page --转换值的顺序
FROM sys.system_internals_allocation_units
WHERE container_id = 72057594043236352
--3.这里创建一个表,用来存放dbcc page的结果
if exists(select * from sys.tables where name = 'dbcc_page')
drop table dbcc_page
go
create table dbcc_page
(
ParentObject varchar(500),
Object varchar(2000),
Field varchar(1000),
Value nvarchar(max)
)
go
--4.参数分别是数据库名,fileid,pageid,显示格式
--注意:这里是在自己的电脑上实验,用的master数据库,大家不要在正是服务器上尝试
/*
--这样会报错,只能采用下面的,建一个存储过程
insert into dbcc_page(ParentObject,Object,Field,Value)
DBCC page(master,1,1401,3) with tableresults
*/
if exists(select * from sys.procedures where name = 'proc_dbcc_page')
drop procedure proc_dbcc_page
go
create procedure proc_dbcc_page
as
DBCC page(master,1,1401,3) with tableresults
go
--5.把dbcc page的结果插入到表中
insert into dbcc_page(ParentObject,Object,Field,Value)
exec proc_dbcc_page
--6.查看数据
select *
from dbcc_page
--过滤大部分其他元数据,选出表test中的数据,与最上面的数据相一致
select OBJECT,
Field,
value
from dbcc_page
where Object like 'Slot%Column%'
/*
OBJECT Field value
Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4 idd 1
Slot 0 Column 2 Offset 0xf Length 7 Length (physical) 7 name abcdefg
Slot 1 Column 1 Offset 0x4 Length 4 Length (physical) 4 idd 2
Slot 1 Column 2 Offset 0xf Length 7 Length (physical) 7 name hijklmn
*/
除了上面所解析的1401页外,我们还可以查看其他的页:
/*
DBCC ind:
DBCC IND(
['database name'|database id],
tablename,
indexid,
-1 shows all indexes and IAMs, -2 just show IAMs
)
PageFID: 页所在的文件号
PagePID: 数据所在文件内的页号
IndexID: 在sys.indexes中的index_id, -1表示所有索引页和IAM页,-2只显示IAM页
PageType:表示页的类型,1是数据页,2是索引页,10是保存页本身的IAM页。
IndexLevel: 是IAM结构的级别。如果0,那么这是索引的叶级别页
*/
select name,
index_id -- 0
from sys.indexes
where object_id = object_id('test')
--1.创建表
if exists(select * from sys.tables where name = 'dbcc_ind')
drop table dbcc_ind
go
create table dbcc_ind
(
PageFID numeric(20),
PagePID numeric(20),
IAMFID numeric(20),
IAMPID numeric(20),
ObjectID numeric(20),
IndexID numeric(20),
PartitionNumber numeric(20),
PartitionID numeric(20),
iam_chain_type nvarchar(100),
PageType numeric(20),
IndexLevel numeric(20),
NextPageFID numeric(20),
NextPagePID numeric(20),
PrevPageFID numeric(20),
PrevPagePID numeric(20)
)
go
--2.建存储过程
if exists(select * from sys.procedures)
drop procedure proc_dbcc_ind
go
create procedure proc_dbcc_ind
as
dbcc ind(master,test,0)
go
insert into dbcc_ind
exec proc_dbcc_ind
--3.一共2页,分别是IAM页1402,数据页1401
select PageFID,
PagePID,
OBJECTID,
IndexID,
PartitionNumber,
PartitionID,
iam_chain_type,
PageType,
IndexLevel,
NextPageFID, --下一页的文件id
NextPagePID, --下一页的页id
PrevPageFID,
PrevPagePID
from dbcc_ind