一个可行的方法是反转过程,让存储过程接受临时表的名称,并使用动态SQL将所需结果填充到临时表中。
当存储过程返回时,调用者可以访问临时表中包含的数据。
create table #fast_cars (name varchar(max), top_speed float);
create table #awesome_people (name varchar(max), age int);
exec GetAmazingThings @name='%Wonder%'
,@cars='#fast_cars'
,@people='#awesome_people'
select name, top_speed from #fast_cars;
select name, age from #awesome_people;
接受表名可以减少“魔法知识”,因为名称是显式提供的,知道哪些表受到影响。它还允许在维护隔离性的同时收集多个调用的结果,包括在嵌套期间。
存储过程可能看起来有点像...
create procedure GetAmazingThings
@name varchar(100),
,@cars varchar(100)
,@people varchar(100)
as
set @cars = quotename(@cars);
declare @sql nvarchar(max);
declare #_cars (name varchar(max), top_speed float);
insert into #_cars (name, top_speed)
select Name, max(LapSpeed)
from TonkaToys
where Name like @name and VehicleType = 'car'
group by Name;
if patindex('[[]#%', @cars) > 0
begin
set @sql = concat(N'
insert into ', @cars, ' (name, top_speed)
select name, top_speed
from #_cars
');
exec sp_executesql @sql;
end
else
begin
select name, top_speed from #cars
end
go
注意:
- 在临时表之间至少存在一个(可能更多)数据副本。
- 如果将动态SQL与主查询隔离开来,则SP会更加清晰。首先查询到一个本地临时表,然后使用动态SQL将其复制到提供的临时表中。
- 如果使用全局临时表,则SP可以创建所需的表结果集。但是,虽然方便,但这可能会有问题,因为全局临时表在会话之间共享。
- 参数也可以用于控制SP“返回”的内容,例如跳过查询或选择作为结果集而不是写入到临时表中。
SqlDataReader
从ADO.NET应用程序中访问多个结果集 - 但是您无法从T-SQL访问多个结果集.....这对我来说从未有过意义,但事实就是这样(至少目前是这样)。 - marc_s