2014-08-30 84 views
4

我正在创建一个处理临时表(#attributeType)的触发器。由于触发器可以被调用多次,我想确定并检查临时表#attributeType是否仍然存在。SQL Server,无法检查是否存在临时表,存在if语句

这是我在触发身体检查临时表代码:

IF OBJECT_ID('tempdb..#attributeType') IS NOT NULL 
    BEGIN 
     DROP TABLE #attributeType 
     SELECT * INTO #attributeType 
     FROM attributeType 
     PRINT 'IN IF'+ CAST(OBJECT_ID('tempdb..#attributeType') AS NVARCHAR(80)) 
    END 
ELSE 
    BEGIN 
     SELECT * INTO #attributeType 
     FROM attributeType 
     PRINT 'IN ELSE'+ CAST(OBJECT_ID('tempdb..#attributeType') AS NVARCHAR(80)) 
    END 

当我通过与F5选择它测试的代码我收到此错误信息,指出#attributeType临时表存在:

Msg 2714, Level 16, State 1, Line 11 
There is already an object named '#attributeType' in the database. 

我知道,在存储过程的#tempTables将尽快SP端删除了,但我仍然不明白为什么我的代码是错误的?

N.B. 当我注释掉ELSE块时,代码有效。

回答

10

你的测试OBJECT_ID('tempdb..#attributeType')工作正常。您可以通过单独运行来测试它,而同一批次中不包含dropcreate

问题是SQL Server在运行它之前解析整个批处理。即使你以前的行删除表

SELECT * INTO #attributeType 

:如果它知道#attributeType存在,它会给出错误的。

一种解决方法是删除该表在不同的批次:

IF OBJECT_ID('tempdb..#attributeType') IS NOT NULL 
    DROP TABLE #attributeType 
GO -- new batch 
SELECT * INTO #attributeType ... 

另一种解决方案是在不同的范围,以创建表:

IF OBJECT_ID('tempdb..#attributeType') IS NOT NULL 
    DROP TABLE #attributeType 
exec ('SELECT * INTO #attributeType ...') 
+0

@ Andomar-解析问题是一种错误? – Luther 2014-08-30 17:19:05

+0

不是一个bug,只是一个原始程度 – Andomar 2014-08-30 17:22:49

+0

通过在触发器的主体中放置一个GO,在GO语句之前声明的变量在新批处理中不可见。猜猜我必须处理这个问题。放置If子句作为第一个语句,然后在触发器主体中执行GO并声明所有变量,其余所有代码都不会将触发器分成两批并使其失败? – Luther 2014-08-30 17:25:32

0

如果您不需要执行在IF..ELSE声明中的任何其他操作,您的代码可以简化为以下内容:

IF OBJECT_ID('tempdb..#attributeType') IS NOT NULL 
BEGIN 
    DROP TABLE #attributeType 
END 

SELECT * 
INTO #attributeType 
FROM attributeType 

In t他的情况下,你避免There is already an object named...错误,你仍然有临时表。

相关问题