Sql server 动态SQL临时表错误

Sql server 动态SQL临时表错误,sql-server,stored-procedures,Sql Server,Stored Procedures,我在MS SQL中发现了一个strage编译错误 假设我们有这样一个存储过程 CREATE PROCEDURE Test @FirstPart bit AS BEGIN if @FirstPart = 1 begin Declare @SQL varchar(max) set @SQL = 'ALTER TABLE #Test ADD Column2 varchar(100)' exec(@SQL) set @SQL = 'ALTER TABLE #Test

我在MS SQL中发现了一个strage编译错误

假设我们有这样一个存储过程

CREATE PROCEDURE Test 
@FirstPart bit 
AS 


BEGIN
if @FirstPart = 1 begin
Declare @SQL varchar(max)
    set @SQL = 'ALTER TABLE #Test ADD Column2 varchar(100)'
    exec(@SQL)

    set @SQL = 'ALTER TABLE #Test ADD Column3 varchar(100)'
    exec(@SQL)
end else        
        SELECT Column1, Column2,Column3 FROM #Test
END
然后在另一个阶段,我们这样做

CREATE TABLE #Test (Column1 varchar(100))    
exec Test 1
通常,这将毫无问题地执行2条alter table语句,但此查询运行时会出错

Msg 207, Level 16, State 1, Procedure Test, Line 15
Invalid column name 'Column2'.
Msg 207, Level 16, State 1, Procedure Test, Line 15
Invalid column name 'Column3'.
有什么想法吗

编辑:

ALTER PROCEDURE Test 

AS 


BEGIN



--if @FirstPart = 1 begin
Declare @SQL varchar(max)
    set @SQL = 'ALTER TABLE #Test ADD Column2 varchar(100)'
    exec(@SQL)

    set @SQL = 'ALTER TABLE #Test ADD Column3 varchar(100)'
    exec(@SQL)
--end else      
        SELECT Column1, Column2,Column3 FROM #Test
END

正如您已经注意到的,查询计划是为整个过程制定的。最有可能的原因是,尝试分析代码需要花费更多的时间,在最坏的情况下,甚至需要分析数据来确定代码的哪些部分将实际执行,哪些部分不会执行

如果您有这种特性,您可能应该将它们分成两个不同的过程。这也将有助于创建更好的计划,当计划使用执行该部分时实际使用的参数值时-假设您的过程中实际有更多功能。

我发现的解决方法是select也应该出现在动态查询中

create  PROCEDURE Test @FirstPart BIT
AS
  BEGIN
      DECLARE @SQL VARCHAR(max)

      SET @SQL = 'ALTER TABLE #Test ADD Column2 varchar(100)'

      EXEC(@SQL)

      SET @SQL = 'ALTER TABLE #Test ADD Column3 varchar(100)'

      EXEC(@SQL)

      EXEC('SELECT Column1,Column2,Column3 FROM  #Test') -- Dynamic query
  END

CREATE TABLE #Test
  (Column1 VARCHAR(100))

EXEC Test 1

当@FirstPart 1出现错误时,我也不认为需要动态查询。我注意到,如果您注释掉程序的else部分,那么在执行时不会出现错误。这对我来说意味着,当调用proc时,if的两边都会被评估错误,而不仅仅是要执行的那一边。我相信SQL就是这样工作的。@NoDisplayName这只是一个小例子,我的初始查询的列数未知,所以我需要动态SQL。另外,我执行过程的方式是使用值1,因此它不可能进入案例1@TabAlleman是的,这确实是问题所在,但它看起来像一个恼人的bug。如果代码甚至没有执行,为什么会出现代码抛出错误的某一部分呢?我认为这与SQL创建执行计划的方式有关。执行计划不知道代码的哪些部分将被执行。一种解决方法是在else查询中使用动态sql。我已经将它们分开了,但我只是想知道为什么sql会这样运行。因为即使你删除了if和run,检查我在post上所做的编辑,它仍然会在程序执行开始之前执行错误的计划。如果您正常运行alter语句,而不使用exec,那么它将工作。如果我没记错的话,从那一点开始的计划只会在以后创建,因为alter tables会导致重新编译。