2011-01-28 65 views
6

背景:有一个存储过程用给定名称的临时表执行“填充”操作。该过程是通用的,因为它检查临时表的模式,然后根据模式执行不同的“内容”。我明白,这有点奇怪,但我不愿意改变它,因为它在大多数情况下都可以正常工作,除了....为什么SQL Server在没有时认为临时表已经存在?

如果我有一个存储过程,它为临时表创建两个不同的模式同名。从逻辑上讲,它仅根据IF的哪个分支创建一个临时表。问题是,当存储过程由SQL Server检查看起来它正在评估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
There is already an object named '#test' in the database.

的IFS内跌幅榜的任何组合(之前或之后创建表DDL)似乎满足SQL检查。

任何想法,我可以做到这一点?例如,我可以告诉SQL不执行语法检查,只是接受sproc原样?

回答

6

这是一个限制。由于#tmp将在新会话中创建并立即丢失,因此动态SQL将不起作用。对于如图所示的确切片段,这样做同样的

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

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

不能有两个创建用..#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 
0

,因为我不工作有SQL 2008,我无法测试它。但据我所知,这是一个解析器问题明确与临时表。同样的情况也很好地工作正常表

来排序了这一点,只是逻辑GO语句

分割你的代码的理想:检查临时表的存在,您创建临时表之前,如果它们存在删除它们,火一去,又做临时表的创建,火一展身手,那么任何后处理,火一展身手,终于再次把它们和火最后去


你可能也想尝试和使用如果上面的代码不能解决这个问题,请使用表格变量而不是临时表格

+0

是感谢您的信息。不幸的是,它是在一个存储过程中创建表,所以它必须在同一批次中(所以它不是GO)。 – 2011-01-28 13:20:05

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 
+0

这将不起作用,因为它会立即超出范围并且不能在外部脚本中使用它需要是全局临时表或临时表的所有用法都需要位于动态SQL中。 – 2011-02-09 17:49:27

2

相反#TEST的,使用完全合格的名称。例如,

[tempdb].[dbo].[temptable] 

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

智能感知会发出抱怨,但您仍然可以创建或更改存储过程。

当用它做,一定要删除它:

DROP TABLE [tempdb].[dbo].[temptable] 
相关问题