SQL Server,无法使用if else语句检查#temporary表是否存在

Lut*_*her 4 t-sql sql-server triggers exists temp-tables

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

这是我在触发器体中检查临时表的代码:

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
Run Code Online (Sandbox Code Playgroud)

当我通过使用F5选择代码来测试代码时,我收到此错误消息,指出#attributeType临时表存在:

Msg 2714, Level 16, State 1, Line 11
There is already an object named '#attributeType' in the database.
Run Code Online (Sandbox Code Playgroud)

我知道在存储过程中,一旦sp结束就会删除#tempTables,但我仍然无法理解为什么我的代码错了?

注意当我注释掉ELSE块时代码有效.

And*_*mar 10

你的测试OBJECT_ID('tempdb..#attributeType')工作正常.您可以通过单独运行它,没有测试它drop,并create在同一批次.

问题是SQL Server在运行它之前解析整个批处理.如果它知道#attributeType存在,则会给出错误:

SELECT * INTO #attributeType
Run Code Online (Sandbox Code Playgroud)

即使您将表格放在上一行中.

一种解决方案是将表放在不同的批处理中:

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

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

IF OBJECT_ID('tempdb..#attributeType') IS NOT NULL
    DROP TABLE #attributeType
exec ('SELECT * INTO #attributeType ...')
Run Code Online (Sandbox Code Playgroud)

  • @Luther:GO不能放在触发器的主体中,因为它不是T-SQL语句; 转到SQL Server客户端工具识别的批处理终结符,并且从未传递给SQL Server.我不确定为什么你有两个不同的SELECT ... INTO语句,但这将是有问题的. (4认同)
  • 我不认为你可以在触发器中使用`go`--底部部分将脱离触发器定义.像`declare @tmp table(id int identity,col1 varchar(50))这样的表变量是否适合你的目的? (3认同)