if..else块

时间:2015-07-27 17:23:06

标签: stored-procedures sql-server-2012

我用这个撞到我的头上。

我们正在开发的API中调用存储过程,存储过程具有以下代码:

if(@StatusCode = 41 and @OperationName != 'convert')
Begin
    EXEC [uspCreateOrg] @RequestID = @_RequestId
End
else
Begin
    EXEC [uspUpsertOrg] @RequestID = @_RequestId
End

使用分析器,我们可以确定'如果'分支是执行的分支,但我们也看到SQL Server正在查看“其他”分支。分支并调用该存储过程并抛出异常。 uspUpsertOrg过程调用DBAmp BulkOps,其中包含以下代码:

create table #errorlog (line varchar(255))
insert into #errorlog
exec @Result = master..xp_cmdshell @Command

-- print output to msgs
declare @line varchar(255)
declare @printCount int
set @printCount = 0
DECLARE tables_cursor CURSOR FOR SELECT line FROM #errorlog
OPEN tables_cursor
FETCH NEXT FROM tables_cursor INTO @line
WHILE (@@FETCH_STATUS <> -1)
BEGIN
   if @line is not null
   begin
      print @line 
      exec SF_Logger @SPName,N'Message', @Line
      set @errorLines = @errorLines + @line
      set @printCount = @printCount +1  
   end
   FETCH NEXT FROM tables_cursor INTO @line
END
deallocate tables_cursor

-- drop temp output table
drop table #errorlog

抛出的异常是#errorLog表不存在。总而言之,我们得到一个例外,即在插入上方的行上创建的临时表在存储过程中不存在甚至不被调用... Fun ...

当我们注释掉对uspUpsertOrg的调用时,一切都按预期工作。当我们将临时表更改为真实表时,它仍然会失败,但如果我们在过程外创建它然后运行该过程,它就可以工作。在任何一种情况下,代码都不会落在“其他”的情况下。分支的意思是“其他”分支。分支将是执行的分支。它几乎就像SQL服务器在所有代码路径中向前看 - 我知道SQL Server为优化等做了那样的事情,但是为什么它会错过表IS在使用之前创建的事实?我以前做过这种事情,从来没有遇到过问题。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

根据Execution Plan Basics上的这篇文章,这个确切的场景会导致algebrizer出现问题,但不会执行您的代码,但会负责生成执行计划。查找当估算计划无效时部分。

我认为这种解决方法适用于您:使用

而不是CREATE语句
SELECT CAST('' as VARCHAR(255)) as line INTO #errorlog