【问题标题】:Is it possible to use a Stored Procedure as a subquery in SQL Server 2008?是否可以在 SQL Server 2008 中使用存储过程作为子查询?
【发布时间】:2011-02-03 17:40:32
【问题描述】:

我有两个存储过程,其中一个返回付款列表,而另一个返回这些付款的摘要,按货币分组。现在,我有一个重复的查询:返回付款列表的存储过程的主查询是返回按货币支付的摘要的存储过程的子查询。我想通过使返回支付列表的存储过程成为返回按货币支付的摘要的存储过程的子查询来消除这种重复性。这在 SQL Server 2008 中是否可行?

【问题讨论】:

    标签: sql-server stored-procedures subquery


    【解决方案1】:

    最好将第一个 proc 转换为 TABLE-VALUED 函数。如果涉及多条语句,需要先定义返回表结构并填充。

    示例:

    CREATE proc getRecords @t char(1)
    as
    set nocouut on;
    -- other statements --
    -- final select
    select * from master..spt_values where type = @t
    GO
    

    -- 变成--

    CREATE FUNCTION fn_getRecords(@t char(1))
    returns @output table(
        name sysname,
        number int,
        type char(1),
        low int,
        high int,
        status int) as
    begin
    -- other statements --
    -- final select
    insert @output
    select * from master..spt_values where type = @t
    return
    end;
    

    但是如果是直接选择(或者可以写成单条语句),那么可以使用高度优化的INLINE tvf形式

    CREATE FUNCTION fn2_getRecords(@t char(1))
    returns table as return
    -- **NO** other statements; single statement table --
    select * from master..spt_values where type = @t
    

    第二个过程只是从第一个过程中选择

    create proc getRecordsByStatus @t char(1)
    as
    select status, COUNT(*) CountRows from dbo.fn2_getRecords(@t)
    group by status
    

    还有你曾经打电话的地方

    EXEC firstProc @param
    

    要获得结果,您现在可以从中选择

    SELECT * FROM firstProc(@param)
    

    【讨论】:

    • 当您的存储过程需要在 CUBE 上运行 OPENQUERY 时会发生什么?您不能在函数中执行此操作。
    【解决方案2】:

    您可以在临时表中捕获存储过程的输出,然后在主查询中使用该表。

    捕获将列 ID 和名称返回到表变量的存储过程的输出。

    declare @T table (ID int, Name nvarchar(50))
    
    insert into @T
    exec StoredProcedure
    

    【讨论】:

    • 对不起...您说的是临时 FILE 吗?虽然这在技术上是一个可行的解决方案,但我认为我不能一直编写和删除巨大的临时文件。
    • 临时表,它已在答案中更正,但只是想澄清一下可能对上述评论过时感到困惑的未来读者。
    • 我希望有一个EXEC INTO #tmp :-)
    【解决方案3】:

    将存储过程的结果插入到表变量或临时表中即可。

    如果您尝试将 SQL Server 中的代码从一个查询重复使用到下一个查询,则可以使用表函数获得更大的灵活性。如果您不需要传递参数或使用任何类型的流控制逻辑,视图就可以了。这些可以像任何其他函数、过程、视图或 t-sql 语句中的表一样使用。

    【讨论】:

    • 我同意杰夫。表值函数非常适合这类事情。
    【解决方案4】:

    如果您将返回列表的过程设为表值函数,那么我相信您可以在子查询中使用它。

    【讨论】:

      【解决方案5】:

      我会使用视图,除非它需要参数化,在这种情况下,如果可能的话,我会使用内联表值函数,除非它需要是多语句操作,你仍然可以使用表-值函数,但它们通常效率较低。

      【讨论】:

      • 我需要带参数来执行这两个查询。这就是我使用存储过程的原因。
      • @Eduardo Leon 如果可能,我会使用内联表值函数。就优化器如何处理它们并将它们与任何底层视图以及调用 ITVF 的任何代码相结合而言,这些实际上等同于参数化视图。
      • 您可以在查询的FROM 子句中调用 ITVF 吗?
      • @Eduado Leon 当然 - 您可以从视图(使用静态或代码生成,如果您生成视图 - 参数)或另一个 ITVF 使用 ITVF。根据我的经验,如果您查看执行计划,优化器会非常有效地折叠所有视图和 ITVF(如果直接加入)。
      猜你喜欢
      • 1970-01-01
      • 2011-03-09
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-26
      • 1970-01-01
      相关资源
      最近更新 更多