七、聚合应该注意的地方
当我们集合结果集时,可以按着下面的方法去做:
当我们集合结果集时,可以按着下面的方法去做:
确认我们的第一个结果集可以为后面的结果集留有位置。
SP_map的@Accumulate标志是非常有用的 ---- 尤其对于返回小结果集的查询来说。我们需要认识道,无认如何,SP_map不能做没有什么规划的事情。如下面的例子,一个常规的查询返回了所有表名的列表。
EXEC sp_msForEachTable " select '?' "
这个查询产生了很多结果集。我们也许会发现我们自己想利用sp_msForEachTablet提供任何查询。这样SP_map将会降低我们的结果集的简单性。第一步要做的在上面已经讨论过了,就是命名一个匿名的列:
EXEC sp_msForEachTable " select '?' as TableName"
接下来我们需要将查询放到字符串中,因此,我们必须使用双引号:
@StmtTemplate = ' EXEC sp_msForEachTable "
select ''?'' as TableName" '
现在,有一点如果不做说明可能会使我们困惑:如果我们只写下面的代码:
... 我们会得到类似下面的错误(除非我们非常幸运):EXEC SP_map @StmtTemplate = ' EXEC sp_msForEachTable " select ''?'' as TableName" ', @Accumulate = 1
Msg 8152, Level 16, State 14, Line 1
String or binary data would be truncated.
那么这是为什么呢? 在上面的代码中通过建立一个临时表重新调用了聚合,它的定义将从第一个结果集推断出来。假设结果集包含一个字符。除非这个结果集正好包含了比其它值都行的字符串,否则字结果集将尝试放一个长的字符串放到这个字段中,因此,就会出现上述的错误。因此,我们必须保证让SP_map知道这个name字段可以容纳多长的字符串,而不考虑在第一个结果集中的值是多长或多短。下面是一种解决方案。如果我们的表有更长的名字,需要使用一个更大的转换值:
EXEC SP_map
@StmtTemplate =
'EXEC sp_msForEachTable "select convert(
varchar(128), ''?'') as Name" ',
@Accumulate = 1
八、确保我们的结果集都有同样的结构
正在使用一个@StmtTemplate的模板,如SELECT * FROM <MAIN_ARG>将仅仅为在参数列表中的每一个表工作。换句话说。我们不能聚合一个包含五列的结果集和一个包含三列的结果集。还有就是聚合工作通过动态地产生一个临时表,并通过第一个结果集的结构推断。每一个子集被合并在这个临时表中。因此,每一列必须和这个临时表的结构兼容。