如何将单个结果集从返回多个集的 SQL 存储过程保存到临时表?
Posted
技术标签:
【中文标题】如何将单个结果集从返回多个集的 SQL 存储过程保存到临时表?【英文标题】:How to save a single result set to a temp table from a SQL stored procedure returning multiple sets? 【发布时间】:2009-10-08 15:56:49 【问题描述】:我需要将存储过程的结果集存储在临时表中(使用 SQL Server 2000)。根据我的阅读,这个(结构不佳的例子)应该可以工作:
create table #tempTable (TempId int primary key, Column1 varchar(100),
Column2 varchar(100), DateCreated datetime)
insert into #tempTable (TempId, Column1, Column2, DateCreated)
exec sproc_Select_Stuff_By_DateCreated @Date1 = '1/1/2009', @Date2 = '1/2/2009'
但我得到: “插入错误:列名或提供的值的数量与表定义不匹配。”
检查程序(我无法编辑)揭示了这一点:
CREATE PROCEDURE sproc_Select_Stuff_By_DateCreated
@Date1 datetime,
@Date2 datetime
AS
BEGIN
SELECT TempId, Column1, Column2, DateCreated
FROM ReallyHugeMessOfJoinsAndCalculatedColumns
WHERE DateCreated between @Date1 and @Date2
SELECT @Date1 as Date1, @Date2 as Date2
END
所以它实际上回显了作为第二个结果集传递给它的参数。 (我不知道为什么;我想任何调用该过程的东西都会知道它传入了什么数据。)
我的测试让我认为第二个结果集是导致插入失败的原因 - 就像 SQL 试图将结果集合并在一起但失败了。
我只需要将第一个结果集保存到我的临时表中。我该怎么做?
编辑
感谢您指出 CLR 存储过程,但该功能是在 SQL 2005 中引入的 - 它不适用于 2000 年。(但我以前不知道它们,当我们使用它们时它们看起来会很有用升级。)
因为唯一的其他答案看起来是“你不能” - 我想这对我来说又回到了绘图板上。
【问题讨论】:
查看相关问题:***.com/questions/58940/…> 这个问题有一个使用 CLR 的解决方法 你能发布一些存储过程的结果吗? 【参考方案1】:由于您无法更改存储过程,因此您只有两个选择:
使用 CLR,它可以捕获两个结果集,并只返回您想要的结果集。 在您自己的过程或视图中复制您需要的查询。这是一个真正的黑客,CLR 是首选。但是,您没有太多选择。【讨论】:
【参考方案2】:通常,在纯 SQL 中这是不可能的。 Brannon 的链接提供了使用 CLR 的可能解决方法。
另一方面,如果重构是一种选择,请考虑在其自己的存储过程中使第一个查询原子化。然后可以从现有的存储过程和任何其他代码中调用它。你的代码仍然只在一个地方,没有任何东西被破坏,你得到的东西可以更容易地从纯 SQL 中使用。根据其功能,SP 的第一部分甚至可能是内联表值函数的良好候选者(我发现它们性能良好且灵活)。然后,您甚至不需要将输出捕获到临时表中,以便在进行其他处理时将其用作表(尽管如果您想多次使用它,您可能需要这样做)! p>
【讨论】:
【参考方案3】:以下是您所讨论内容的完整、有效(适用于 SQL 2005)示例。
坏消息是,我不相信有任何方法可以做你想做的事情。对不起。看起来 SP 编写者让它变得不可能。
如果有人想出一些创造性的方法来完成这项工作,那就太好了!
IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL
DROP TABLE #tempTable
GO
IF EXISTS (SELECT * FROM sys.procedures WHERE name = 'sproc_Select_Stuff_By_DateCreated')
DROP PROCEDURE dbo.sproc_Select_Stuff_By_DateCreated
GO
CREATE PROCEDURE dbo.sproc_Select_Stuff_By_DateCreated
@Date1 datetime,
@Date2 datetime
AS BEGIN
;WITH t AS (
SELECT
1 AS TempId,
'Column1-val1' AS Column1,
'Column2-val1' AS Column2,
'2009-01-01 10:00:00' AS DateCreated
UNION ALL
SELECT
2,
'Column1-val2',
'Column2-val2',
'2009-01-01 11:00:00'
)
SELECT
TempId,
Column1,
Column2,
DateCreated
FROM t -- ReallyHugeMessOfJoinsAndCalculatedColumns
WHERE DateCreated between @Date1 and @Date2
SELECT @Date1 as Date1, @Date2 as Date2
END
GO
create table #tempTable (
TempId int primary key,
Column1 varchar(100),
Column2 varchar(100),
DateCreated datetime
)
insert into #tempTable (TempId, Column1, Column2, DateCreated)
exec dbo.sproc_Select_Stuff_By_DateCreated
@Date1 = '1/1/2009',
@Date2 = '1/2/2009'
--SELECT * FROM #tempTable
----------------------------------------
Msg 213, Level 16, State 7, Procedure sproc_Select_Stuff_By_DateCreated, Line 26
Insert Error: Column name or number of supplied values does not match table definition.
【讨论】:
【参考方案4】:来自Microsoft T-SQL reference
INSERT EmployeeSales
EXECUTE uspGetEmployeeSales;
GO
【讨论】:
以上是关于如何将单个结果集从返回多个集的 SQL 存储过程保存到临时表?的主要内容,如果未能解决你的问题,请参考以下文章
数据访问设计:多个结果集单个存储过程或每个存储过程单个结果集