【IT168 专稿】
在SQL Server2005中实现数组映射(一)
四、重新访问聚合映射
到现在为止我们已经学会了如何通过一系列参数来聚合一条简单的SELECT语句。但是这样仅仅在与如sp_who这样的存储过程联合时才有用。sp_who可以列出当前的用户,或使用sp_spaceused,这个存储过程可以返回关于表、视图或查询。行数和磁盘信息。如下面的代码使用SP_map对两个表调用了sp_spaceused:
EXEC SP_map
@StmtTemplate = "execute sp_spaceused <MAIN_ARG>",
@MainArray = 'Users, Permissions',
@Accumulate = 0
我们看到的@Accumulate标志,将多个结果集合为了一个。但使用存储过程做这件事和使用简单的SELECT语句是有很大差异的。如果我们编辑上面的代码,将@Accumulate打开,并设置@Verbose为1,SP_map将返回如下的代码:
-- TEMPLATE (create): SELECT * INTO #Map_Temp_Table FROM OPENROWSET ('SQLOLEDB', 'Server=(local)\SqlExpress;TRUSTED_CONNECTION=YES;', 'set fmtonly off execute dbo.sp_spaceused <MAIN_ARG>') -- TEMPLATE (update): INSERT INTO #Map_Temp_Table SELECT * FROM OPENROWSET ('SQLOLEDB', 'Server=(local)\SqlExpress;TRUSTED_CONNECTION=YES;', 'set fmtonly off execute dbo.sp_spaceused <MAIN_ARG>') SELECT * INTO #Map_Temp_Table FROM OPENROWSET ('SQLOLEDB','Server=(local)\SqlExpress;TRUSTED_CONNECTION=YES;', 'set fmtonly off execute dbo.sp_spaceused Users') INSERT INTO #Map_Temp_Table SELECT * FROM OPENROWSET ('SQLOLEDB','Server=(local)\SqlExpress;TRUSTED_CONNECTION=YES;', 'set fmtonly off execute dbo.sp_spaceused Permissions') select * from #Map_Temp_Table drop table #Map_Temp_Table
当按通常方法调用上面的语句时(不使用SP_map包装),存储过程将返回单独的结果集。但是一个特殊的存储过程—sp_msForEachTable-可以返回多个结果集(每一个表是一个结果集)。为了显示所有表的结果集,可以使用下面的标准调用方式,代码如下:
EXEC sp_msForEachTable "EXEC sp_spaceused '?'"
SP_map还只要在语句上稍加修改,就可以将输出结果转换为一个结果集。代码如下:
EXEC SP_map
@StmtTemplate = 'EXEC sp_msForEachTable
"EXEC sp_spaceused ''?''"', @Accumulate = 1
要注意的是,只有我们不用支持@MainArray作为参数时,还可以在SP_map中包装返回多个结果集的存储过程。而@MainArray,在这种情况下,已经在表名集合中被隐含定义了。上面调用SP_map后将产生如下的代码:
- TEMPLATE (create): SELECT * INTO #Map_Temp_Table FROM OPENROWSET ( 'SQLOLEDB', 'Server=(local)\SqlExpress;TRUSTED_CONNECTION=YES;', 'set fmtonly off EXEC dbo.sp_msForEachTable "select convert(varchar(128), ''?'') as Name"') TRUNCATE TABLE #Map_Temp_Table INSERT INTO #Map_Temp_Table EXEC dbo.sp_msForEachTable "select convert(varchar(128), '?') as Name" SELECT * INTO #Map_Temp_Table FROM OPENROWSET ( 'SQLOLEDB', 'Server=(local)\SqlExpress;TRUSTED_CONNECTION=YES;', 'set fmtonly off EXEC dbo.sp_msForEachTable "select convert(varchar(128), ''?'') as Name" ') TRUNCATE TABLE #Map_Temp_Table INSERT INTO #Map_Temp_Table EXEC dbo.sp_msForEachTable "select convert(varchar(128), '?') as Name" select * from #Map_Temp_Table drop table #Map_Temp_Table
这时,代码仅仅产生了一个CREATE模板,并没有UPDATE模板。还有,这个CREATE模板没有占位符。SP_map并没有扫描一个按着正常方式调用的存储过程返回的列表。而是由强大的sp_msForEachTable存储过程通过自身进行的扫描。