具有动态结果的存储过程到临时表中

Posted

技术标签:

【中文标题】具有动态结果的存储过程到临时表中【英文标题】:Stored Procedure with dynamic result into temp table 【发布时间】:2016-05-21 07:33:42 【问题描述】:

我在 SQL 2014 中有一个存储过程,它在内部进行动态查询并返回两个静态列,其余列是动态的。如果我需要将我的 sp 的结果放入一个临时表中,我需要专门使用列名和数据类型来创建我的临时表。

如何在不声明临时表的情况下将结果放入临时表?

我是这样称呼它的:

SELECT * INTO #TempTable 
FROM OPENROWSET
('SQLNCLI','Server=cimplsql-d1.turtle.local;Trusted_Connection=yes;', 'EXEC [dbo].[AttributeSelect] ''2016-01-01'', ''2016-01-01'', 1')

我无法很好地定义我的临时表,因为结果是动态的,它可以返回 4、10 或 20 列,我不知道。

这是现在的错误:

The metadata could not be determined because statement 'EXEC SP_EXECUTESQL @Qry;' in procedure 'AttributeEntitiesSelect'  contains dynamic SQL.  Consider using the WITH RESULT SETS clause to explicitly describe the result set.

我在 sp 中的动态 sql 上使用了 WITH RESULT SETS UNDEFINED 选项,但没有用

【问题讨论】:

Insert results of a Stored Procedure into a Temporary Table的可能重复 【参考方案1】:

您需要使用打开的行集

SELECT * INTO #TempTable 
FROM OPENROWSET
('SQLNCLI','Server=yourservername;Trusted_Connection=yes;',
     'EXEC OtherDb.DataProd.abc')

SELECT * FROM #TempTable

行集处理查询结果,而不是查询。所以动态表是可能的,此外您还需要启用即席分布式查询

摘自 MSDN:

是一个字符串常量,发送给提供者并由提供者执行。 SQL Server 的本地实例不处理此查询,而是处理提供程序返回的查询结果,即传递查询。传递查询在用于不通过表名而仅通过命令语言提供其表格数据的提供程序时很有用。只要查询提供程序支持 OLE DB Command 对象及其强制接口,远程服务器就支持直通查询

参考资料: Exec stored procedure into dynamic temp table

已根据错误消息进行编辑: 我运行分析器来查看当我们调用行集时发生了什么,我可以看到行集在 sp 下面使用来获取要插入的表的元数据..

尝试在 sp 下执行,如果它不起作用,问题出在你的 sp..

exec [sys].sp_describe_first_result_set N'EXEC tempdb.[dbo].usp_test ''sateesh''',NULL,1

我还创建了一个 sp 来测试,我看不出任何问题..

select * into #temp from openrowset
('SQLNCLI','Server=tejith\sateesh;Trusted_Connection=yes;', 'EXEC tempdb.[dbo].usp_test ''sateesh''')

【讨论】:

但是我在同一个db上,还需要这样用吗? 已编辑,看看有没有帮助 我收到此错误:消息 11529,级别 16,状态 1,过程 sp_describe_first_result_set,第 158 行 无法确定元数据,因为每个代码路径都会导致错误;请参阅之前的一些错误。消息 2812,级别 16,状态 62,过程 sp_describe_first_result_set,第 158 行找不到存储过程“pit.AttributeEntitiesSelect”。 可能是你提供的 spname 错误。如果我在名为 test 的数据库中有一个 sp,我会像 exec test.dbo.usp_testproc 显然它不喜欢我存储过程中的临时表,现在我有了这个:无法确定元数据,因为语句使用了临时表。【参考方案2】:

由于您的查询是针对同一台服务器运行的(但也应该针对远程服务器运行),我认为您可以这样处理它:

1) 定义一个指向同一个实例的链接服务器。我们称之为loopback

2) 使用OPENQUERY

SELECT * INTO #TempTable 
FROM FROM OPENQUERY(loopback, 
    'set fmtonly off exec loopback.yourdb.dbo.yourprocedure 
    WITH RESULT SETS ((@param1 INT, @param2 VARCHAR(20)))');

WITH RESULT SETS 是必需的,因为SQL2012

【讨论】:

以上是关于具有动态结果的存储过程到临时表中的主要内容,如果未能解决你的问题,请参考以下文章

SQL存储过程多个结果到临时表中

在存储过程中调用别的存储过程,把结果保存到临时表中

为啥这个 SQL 存储过程需要创建一个临时表才能工作(返回结果)?

MySQL 存储过程,获取使用游标查询的结果集

将存储过程结果插入临时表

转:把存储过程结果集SELECT INTO到临时表