【问题标题】:nested insert exec work around嵌套插入 exec 解决方法
【发布时间】:2010-03-24 19:55:55
【问题描述】:

我有 2 个存储过程 usp_SP1 和 usp_SP2。他们都使用插入到#tt exec sp_somesp。我想创建一个第三个存储过程,它将决定调用哪个存储过程。比如:

create proc usp_Decision
(
   @value int
)
as
begin
   if (@value = 1)
     exec usp_SP1  -- this proc already has insert into #tt exec usp_somestoredproc
   else
        exec usp_SP2  -- this proc too has insert into #tt exec usp_somestoredproc
end

后来,我意识到我需要为来自 usp_Decision 的返回值定义一些结构,以便我可以填充 SSRS 数据集字段。所以这是我尝试过的:

  1. 在 usp_Decision 中创建了一个临时表并尝试执行“插入 #tt exec usp_SP1”。这没有成功。错误“插入 exec 不能嵌套”

  2. 在 usp_Decision 中尝试将表变量传递给每个存储过程并更新存储过程中的表并执行“select * from”。那也没有成功。作为参数传递的表变量不能在存储过程中修改。

请建议可以做什么。

【问题讨论】:

标签: sql-server tsql sql-server-2008 stored-procedures


【解决方案1】:

可以修改usp_SP1和usp_SP2吗?

如果是这样,在 usp_Decision 中,使用适当的架构创建一个本地临时表来插入结果:

create table #results (....)

然后,在被调用的过程中,测试这个临时表是否存在。如果存在,则插入到临时表中。如果不是,则照常返回结果集。如果从其他地方调用嵌套过程,这有助于保留现有行为。

if object_id('tempdb..#results') is not null begin
  insert #results (....)
  select .....
end
else begin
  select ....
end

当控制返回到调用过程时,#results 将由嵌套过程填充,无论哪个被调用。

如果结果集不共享相同的架构,您可能需要在 usp_Decision 中创建两个临时表。

【讨论】:

    【解决方案2】:

    您是否了解过表值用户定义函数(内联或多语句)?与 HLGEM 的建议类似,这将返回一个您可能不必在任何位置插入的集合。

    【讨论】:

      【解决方案3】:

      无论如何都不喜欢全局临时表(其他进程可以读取这些表并可能干扰其中的数据)。

      为什么不让每个 proc 使用本地临时表并从该表中选择 * 作为最后一步。 然后您可以在调用过程中插入本地临时表。

      简单示例

      create proc usp_mytest1
      as
      select top 1 id into #test1
      from MYDATABASE..MYTABLE (nolock)
      
      select * from #test1
      go
      --drop table #test
      create proc usp_mytest2
      as
      select top 10 MYTABLE_id into #test2
      from MYDATABASE..MYTABLE (nolock)
      
      select * from #test2
      go
      
      create proc usp_mytest3 (@myvalue int)
      as
      create table #test3 (MYTABLE_id int)
      if @myvalue = 1
      Begin
      insert #test3
      exec ap2work..usp_mytest1
      end
      else
      begin
      insert #test3
      exec ap2work..usp_mytest2
      end
      
      select * from #test3
      
      go
      
      exec ap2work..usp_mytest3 1
      
      exec ap2work..usp_mytest3 0
      

      【讨论】:

      • 我在每个存储过程中使用本地临时表,因此“插入到 #tt exec usp_somestored 过程中”。现在我想在 usp_Decision 存储过程中从 #tt_example 中选择 * 我必须先插入到 #tt_example exec usp_SP1 中。但这是不允许的。我不确定这是否是您建议的方法。如果不是,请用一些伪代码解释一下。
      • 我在我的存储过程中都使用插入到#tt exec sp_executesql @query 中,因此上述方法不起作用。
      • 现在我刚刚将两个存储的过程合并为一个。这是一个巨大的,但现在可以使用。
      【解决方案4】:

      请参阅此blog article 了解一种解决方法(使用 OPENROWSET 实质上创建一个环回连接,在该连接上发生 INSERT EXEC 调用之一)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-12
        • 1970-01-01
        • 1970-01-01
        • 2014-02-07
        相关资源
        最近更新 更多