为什么SQL Server认为Temp Table已经存在?

时间:2011-01-28 12:35:03

标签: sql-server tsql sql-server-2008-r2

背景:有一个存储过程,它使用给定名称的临时表来“填充”。该过程是通用的,因为它检查临时表的模式,然后根据模式执行不同的“东西”。我知道这有点奇怪,但我不愿意改变它,因为它在大多数情况下都能正常工作,除了....

如果我有一个存储过程,它为具有相同名称的临时表创建两个不同的模式。从逻辑上讲,它只根据IF的哪个分支创建一个临时表。问题是,当SQL Server检查Sproc时,它似乎正在评估IF的两端(如果它正在检查SQL语法,这是有意义的。)

所以这个SQL失败了:

IF (1=1)
BEGIN
    CREATE TABLE #test
    (
        a BIGINT NOT NULL,
        b BIGINT NOT NULL
    )
END 
ELSE
BEGIN
    CREATE TABLE #test
    (
        a BIGINT NOT NULL,
        b BIGINT NOT NULL,
        c BIGINT NOT NULL   
    )   
END

--exec SomeProcedureWhichDoesStuffWith#Test

DROP TABLE #test 

出现以下错误:

  

Msg 2714,Level 16,State 1,Line 14
  已经有一个名为的对象   数据库中的'#test'。

ifs内部(在create table DDL之前或之后)没有drop table的组合似乎满足sql检查器。

我有什么想法可以做到这一点?例如,我可以告诉SQL不执行语法检查并按原样接受sproc吗?

4 个答案:

答案 0 :(得分:7)

这是一个限制。动态SQL也不起作用,因为#tmp将在新会话中创建并立即丢失。对于如图所示的EXACT代码段,它执行相同的

CREATE TABLE #test
(
    a BIGINT NOT NULL,
    b BIGINT NOT NULL
)

IF not (1=1)
    ALTER TABLE #test ADD c BIGINT NOT NULL   

同一批次中不能有两个CREATE ..#name,但这也可以通用形式

IF (1=1)
BEGIN
    CREATE TABLE #test
    (
        a BIGINT NOT NULL,
        b BIGINT NOT NULL
    );
END 
GO

IF NOT (1=1)
BEGIN
    CREATE TABLE #test
    (
        a BIGINT NOT NULL,
        b BIGINT NOT NULL,
        c BIGINT NOT NULL   
    )
END

答案 1 :(得分:2)

使用完全限定名称而不是#test。例如,

[tempdb].[dbo].[temptable]

我在这里学到了这个小技巧Insert result of executing dynamic query into a table

Intellisense会抱怨,但您仍然可以创建或更改存储过程。

完成后,请务必放弃它:

DROP TABLE [tempdb].[dbo].[temptable]

答案 2 :(得分:0)

因为我没有sql 2008,所以我无法测试它。但据我所知,这是一个明确的临时表的解析器问题。同样适用于普通表

要对此进行排序,只需使用逻辑GO语句拆分代码

理想情况下:在创建临时表之前检查是否存在临时表,如果它们存在则删除它们,触发,再次创建临时表,触发,然后进行任何后处理,触发,最后再次放弃它们,最后一次开火


你可能还想尝试使用表变量而不是临时表,如果上面没有为你解决它

答案 3 :(得分:0)

你总是可以“作弊”:

DECLARE @SQL VARCHAR(200)

IF (1=1)
BEGIN
    SET @SQL = 'CREATE TABLE #Temp     ' +
               '(                      ' +
               '    a BIGINT NOT NULL, ' +
               '    b BIGINT NOT NULL  ' +
               ')                      '
END
ELSE
BEGIN
    SET @SQL = 'CREATE TABLE #Temp     ' +
               '(                      ' +
               '    a BIGINT NOT NULL, ' +
               '    b BIGINT NOT NULL, ' +
               '    c BIGINT NOT NULL  ' +
               ')                      '
END

EXEC SP_EXECUTESQL @SQL