我有一个调用另一个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
答案 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的查询,请执行此操作。这将运行得更好,因为在计划中将忽略未使用的表和列,实际上不需要包括。