根据SP的结果集动态创建临时表

时间:2009-03-13 13:20:04

标签: sql-server sql-server-2005 tsql

我有一个调用另一个SP的SP,结果集只需要过滤到我感兴趣的列。

DECLARE @myTable TABLE
(
  Field1 INT,
  Field2 INT,
  Field3 INT
)

--If someSP returns say 30 params and I need only 3 params, I don't want to declare all 30 in my temp table @myTable

INSERT INTO @myTable
(Field1, Field2, Field3)   
EXEC someSP          --Need to selectively filter recordset from SP
  @InputParam1 = 'test'

如果我不能这样做,我想基于someSP的结果集创建临时表DYNAMICALLY(这样,当someSP被修改为添加新的param时,它减轻了维护问题,我也不需要修改此proc

5 个答案:

答案 0 :(得分:2)

简短回答:不,你做不到。

您必须预先声明临时表,其中包含将从存储过程返回的确切列数。

解决方法是使用持久表。例如,您可以在数据库中拥有一个名为someSPResults的永久表。每当someSP更改为具有不同数量的输出列时,请在部署过程中更改someSPResults的格式。

然后你可以这样做:

insert into dbo.someSPresults
exec someSP

或者在someSP中,您可以将结果直接插入someSPresults表中作为执行的正常部分。您只需要确保确定someSPresults表中的每个执行someSresults表中的哪些记录,因为存储过程可以同时多次触发,从而将大量数据转储到某些SP结果中。

答案 1 :(得分:1)

cmsjr声明,“表变量不能是另一个存储过程的结果集的目标。”

我认为这也是真的,但后来我测试了它。此代码适用于2005年和2008年:

CREATE PROCEDURE someSP (@InputParam1 varchar(100)) AS
SELECT LEN(@InputParam1), DATALENGTH(@InputParam1), @@SPID
GO

DECLARE @myTable TABLE (
    Field1 INT,
    Field2 INT,
    Field3 INT
)

INSERT INTO @myTable (Field1, Field2, Field3)   
EXEC someSP
    @InputParam1 = 'test'

SELECT * FROM @myTable

我知道这可以用于#temp表,但我认为它不适用于@temp表。

但这并没有回答DotnetDude的问题。

答案 2 :(得分:0)

表变量不能是来自另一个存储过程的结果集的目标,也不能在声明它们后对表变量执行DDL,它们将始终具有与声明它们相同的定义。临时表是你最好的选择。

答案 3 :(得分:0)

我可以想到两个选项,但我没有时间测试它们:将SP转换为用户定义函数并使用SELECT * FROM {function} INTO {table},或者使用OPENROWSET:

SELECT *
FROM OPENROWSET('SQLOLEDB',
                'servername';'username';'password',
                'exec dbname.{owner}.yourstoredproc') AS spResult
INTO {tablename}

两种解决方案都应该动态创建表格,然后您只需从中进行选择即可。

答案 4 :(得分:0)

基于上面的评论,我建议你考虑一个表值函数。 这可以参数化,你可以这样做:

INSERT @foo (col1, col14, col29)
SELECT col1, col14, col29 FROM dbo.ufnTVF (@p1, @p2)

否则,它是OPENROWSET作为“最干净”(我使用这个松散的)解决方案

或者,您将存储过程的结果集修改为onlky返回所需的列。 这意味着动态SQL或许多IF语句。在某些情况下,这将无法正确解析(使用SET FMTONLY等)。

您可能正在尝试对第三方应用或系统存储过程进行编码(我们没有完整的详细信息),但它感觉凌乱和错误。 SQL Server 2005拥有大量的DMV和目录(或目录,具体取决于您所在的大西洋的哪一侧)视图,无需系统转发调用。

如果你试图模仿OO设计的某些方面(一个为每个男孩做一些事情的过程),那么我不会。如果您需要重新打包3列30的查询,请执行此操作。这将运行得更好,因为在计划中将忽略未使用的表和列,实际上不需要包括。