【问题标题】:Dynamically create temp table based on resultset from SP根据 SP 的结果集动态创建临时表
【发布时间】:2009-03-13 13:20:04
【问题描述】:

我有一个调用另一个 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 的结果集动态创建临时表(这样可以在修改 someSP 以添加新参数时减轻维护问题,我也不需要修改这个过程

【问题讨论】:

  • 同一个用户非常相似:stackoverflow.com/questions/630584/…
  • 是的 - 我之前的帖子没有得到太多回复。我不想走上使用 OPENROWSET 的路线,并且还想到了动态创建临时表的想法,这与前一个 Q 本质上不同。抱歉,如果您觉得它是重复的帖子

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


【解决方案1】:

简短回答:不,你不能那样做。

您必须使用将从存储过程返回的确切列数预先声明您的临时表。

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

那么你可以这样做:

insert into dbo.someSPresults
exec someSP

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

【讨论】:

    【解决方案2】:

    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 的问题。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

        两种解决方案都应该即时创建表,然后您可以简单地从中进行选择。

        【讨论】:

          【解决方案5】:

          基于上述 cmets,我建议您考虑使用表值函数。 这可以参数化,你可以这样做:

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

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

          或者,您修改存储过程的结果集以仅返回您想要的列。 这意味着动态 SQL 或大量 IF 语句。在某些情况下无法正确解析(使用 SET FMTONLY 等)。

          您可能正在尝试针对 3rd 方应用程序或系统存储的过程进行编码(我们没有完整的详细信息),但感觉很混乱和错误。 SQL Server 2005 有大量 DMV 和目录(或目录,取决于您在大西洋的哪一边)视图,无需系统 proc 调用。

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

          【讨论】:

            猜你喜欢
            • 2011-12-11
            • 2011-05-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多