如何在存储过程B中,对存储过程A的结果集进行查询

 

问题:

 

有读者来信询问:如何在存储过程B里面使用存储过程A执行后的结果集?就是在存储过程B里面再对存储过程A的结果集进行查询。

 

解答:

 

建议您在存储过程中将另外一个存储过程的结果集先存放到一个暂存数据表,接着对此暂存数据表进行查询处理之后,然后再将最终的处理结果传出。

 

在此我们将示范如何在存储过程中使用名称以 # 开头的区域性暂存数据表以及table数据类型的变量来储存另外一个存储过程的结果集,并进行后续的处理。

 

程序范例一

 

 

图表1

 

以下的程序代码会先建立一个查询所有薪资与性别的存储过程uspGetIncome,接着建立一个以「性别」为查询条件的存储过程uspGetTotalIncomeByGender。在存储过程uspGetTotalIncomeByGender中,我们会建立一个名称为 #tmpTable 的暂存数据表,然后使用INSERT INTO ... EXECUTE <存储过程> 表达式将另外一个存储过程 uspGetIncome 的结果集新增至暂存数据表中,接着以「性别」为分类条件,使用 SUM 函式来计算出不同性别的收入总计。最后,我们分别以男性与女性为输入参数呼叫存储过程 uspGetTotalIncomeByGender(执行结果如图表1所示):

 

...

-- 查询目前薪资之SP

CREATE PROCEDURE dbo.uspGetIncome

AS

SELECT 目前薪资, 性别 FROM 章立民研究室;

GO

 

-- 建立以「性别」为查询条件的 SP

-- 这个 SP 会呼叫上面的 SP

CREATE PROCEDURE dbo.uspGetTotalIncomeByGender

  @Gender nvarchar(1)

AS

-- 建立一个暂存数据表

CREATE TABLE #tmpTable (目前薪资 money, 性别 nvarchar(1));

INSERT INTO #tmpTable EXECUTE dbo.uspGetIncome;

-- 取得以性别为分类条件的收入总计

SELECT SUM(目前薪资) AS 收入总计 FROM #tmpTable WHERE 性别 = @Gender;

GO

 

-- 查询性别为「男」的员工收入总计

EXECUTE dbo.uspGetTotalIncomeByGender '';

GO

 

-- 查询性别为「女」的员工收入总计

-- 省略 EXECUTE 关键词

-- 并指定 @Gender 这个参数名称来执行SP

-- 请注意,此时 SP 必须是表达式的第一道指令

dbo.uspGetTotalIncomeByGender @Gender = '';

GO

 

程序范例二

 

 

图表2

 

本程序范例示范如何使用table数据类型的变量来暂存存储过程uspGetAllEmployees的结果集,它会从「章立民研究室」数据表查询出所有员工的姓名、性别以及部门等数据。另外一个存储过程uspGetEmployeeByDeptAndGender需要两个输入参数,分别用来筛选部门与性别之用。

 

由于我们已经将存储过程 uspGetAllEmployees 的结果集储存到 table 数据类型的变量中,此时只需在 SELECT 表达式的WHERE条件子句中,将输入参数带入,即可由 table 数据类型变量中,将某个部门之特定性别的员工数据查询出来(执行结果如图表2所示)。程序代码如下所列:

 

...

-- 取得所有员工数据之 SP

CREATE PROCEDURE dbo.uspGetAllEmployees

AS

SELECT 姓名, 性别, 部门 FROM 章立民研究室

GO

 

-- 建立以「部门」、「性别」为查询条件的SP

-- 这个 SP 会呼叫上面的 SP

CREATE PROCEDURE dbo.uspGetEmployeeByDeptAndGender

@Dept nvarchar(10),

@Gender nvarchar(1)

AS

-- 建立一个 table 数据类型的变量

DECLARE @tmpTable table (姓名 nvarchar(10), 性别 nvarchar(1), 部门nvarchar(10));

INSERT INTO @tmpTable EXECUTE dbo.uspGetAllEmployees;

SELECT * FROM @tmpTable WHERE 部门 = @Dept AND 性别 = @Gender ORDER BY 1;

GO

 

-- 查询部门为「业务部」、性别为「女」性的员工数据

-- 指明 SP 的参数名称,因此参数顺序可以不按照 SP 的参数顺序

EXECUTE dbo.uspGetEmployeeByDeptAndGender @Gender = '', @Dept = '业务部';

GO

 

-- 与上个范例相同,但是没有指明 SP 的参数名称

-- 因此参数顺序必须依照 SP 的参数顺序

EXECUTE dbo.uspGetEmployeeByDeptAndGender '业务部', '';

GO

 

-- 与上个范例相同,只是省略 EXECUTE 这个关键词来执行 SP

dbo.uspGetEmployeeByDeptAndGender '业务部', '';

GO

 

 

附注:
关于使用table数据类型的好处,请参考章立民研究室所撰写的Microsoft® SQL Server 2005完全实战」一书。

 

 

 

 

posted on 2006-11-10 16:55 章立民研究室 阅读(3073) 评论(9)  编辑 收藏 网摘 所属分类: SQL Server 2005

评论

#1楼 2006-11-10 17:51 高海东      

你的这个页面的颜色把别人的眼睛看瞎了   回复  引用  查看    

#2楼 2006-11-10 20:01 san[匿名][未注册用户]

颜色简直是害人。呵呵   回复  引用    

#3楼 2006-11-11 00:12 antony.net      

最后其实说一个临时表和变量表的区别吧。   回复  引用  查看    

#4楼 2006-11-11 12:31 codefan[未注册用户]

同意楼上的,应该说说临时表和表变量的区别。   回复  引用    

#5楼 2006-11-11 23:38 嘻哈呵嘿      

我前两天刚买了本楼主的书。C# 2005的。三天就看完了。 :)   回复  引用  查看    

#6楼 2006-12-01 16:36 zyli[未注册用户]

我做了验证,程序范例二的这种方法是错误的。
我查了sql server联机丛书,里面是这样说的:
注释
可将函数和变量声明为 table 类型。table 变量可用于函数、存储过程和批处理中。

尽可能使用表变量而不使用临时表。table 变量有以下优点:

table 变量的行为类似于局部变量,有明确定义的作用域。该作用域为声明该变量的函数、存储过程或批处理。
在其作用域内,table 变量可像常规表那样使用。该变量可应用于 SELECT、INSERT、UPDATE 和 DELETE 语句中用到表或表的表达式的地方。但是,table 不能用在下列语句中:

INSERT INTO table_variable EXEC 存储过程。

SELECT select_list INTO table_variable 语句。

在定义 table 变量的函数、存储过程或批处理结束时,自动清除 table 变量。

在存储过程中使用表变量与使用临时表相比,减少了存储过程的重新编译量。


涉及表变量的事务只在表变量更新期间存在。这样就减少了表变量对锁定和记录资源的需求。
不支持在表变量之间进行赋值操作。另外,由于表变量作用域有限,并且不是持久数据库的一部分,因而不受事务回滚的影响。
  回复  引用    

#7楼 2007-01-15 21:19 sharewind      

看起来眼睛狂晕,那个颜色好像不太好!呵呵!
楼上的这位大哥讲的不错!
  回复  引用  查看    

#8楼 2007-04-10 09:09 海纳百川

谢了章老师。   回复  引用    

#9楼 2008-04-15 20:03 海宏[未注册用户]

帅哥,能否直接把表变量作为参数传给存储过程?
gselec#126.com
  回复  引用    

导航

公告


章立民
六度当选MVP
七十本著作酿成
十九载作者生涯
现在有了章立民研究室
依旧陶醉在写作的生活里。

统计

与我联系

搜索

 

常用链接

留言簿

随笔分类(111)

随笔档案(112)

光盘勘误下载

最新随笔

积分与排名

最新评论

阅读排行榜

评论排行榜