【问题标题】:Why can I not reuse temp tables in T-SQL?为什么我不能在 T-SQL 中重用临时表?
【发布时间】:2011-05-12 02:37:09
【问题描述】:

这里有一些示例代码:

if object_id('tempdb..#TempList') is not null drop table #TempList

create table #TempList (
   ID int,
   Name varchar(20)
)

insert into #TempList values (1, 'Alpha')
insert into #TempList values (2, 'Beta')
insert into #TempList values (3, 'Gamma')
insert into #TempList values (4, 'Delta')
insert into #TempList values (5, 'Omega')

select * from #TempList

if object_id('tempdb..#TempList') is not null drop table #TempList
drop table #TempList

create table #TempList (
   ID_New int,
   AnotherID int,
   Name_New varchar(40)
)

insert into #TempList values (100, 110, 'Orange')
insert into #TempList values (101, 111, 'Red')
insert into #TempList values (102, 112, 'Purple')
insert into #TempList values (103, 113, 'Blue')
insert into #TempList values (104, 114, 'Green')

select * from #TempList

这会产生以下错误:

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

我不能在同一个 SQL 脚本中重复使用同一个临时表名称吗?有没有办法重复使用相同的临时表名称?

谢谢。

【问题讨论】:

  • 还有一个全局的##tempTables,可以在一个连接下用于不同的查询,你可以在开始时用##命名来声明全局临时表

标签: sql sql-server temp-tables


【解决方案1】:

改变

if object_id('tempdb..#TempList') is not null drop table #TempList
drop table #TempList

create table #TempList (

if object_id('tempdb..#TempList') is not null drop table #TempList
drop table #TempList

GO;

create table #TempList (

SQL Server 查询优化器感到困惑。

它看到你第二次创建同一个表。
请注意,表删除(以及创建)具有概率结果,
结果只会在运行时知道 (不是基于语法控制或查询执行计划创建,也就是 SQL Server 行话中的“编译”)

【讨论】:

  • 我不知道为什么以前没有人回答,因为它是为什么/何时使用 GO 的经典说明。另一种避免错误的方法是逐条执行
  • 我不允许在存储过程中写GO,我如何在SQL server 2012中执行这个存储过程
【解决方案2】:

对我来说似乎是一个解析器错误。我打赌它会看到两个创建表语句创建同一个表并抛出错误,无论 drop 语句如何。不过,使用 go 语句将其分解也可以。

create table #Temp (ID int)
insert into #Temp (ID)
select 1 union all select 2

select ID from #Temp

drop table #Temp
go
create table #Temp (ID int)

insert into #Temp (ID)
select 10 union all select 11

select ID from #Temp

drop table #Temp

【讨论】:

    【解决方案3】:

    这是范围和#temp 表的问题。由于您可以使用同名的#temp 表建立两个连接,因此元数据不会直接以您指定的名称引用它。

    this blog post 中非常彻底地解释了这种行为。

    您需要使用LIKE 比较运行不同的查询以删除#temp 表:

    IF EXISTS (
    SELECT *
    FROM sys.tables
    WHERE name LIKE '#templist%')
    DROP TABLE #templist
    CREATE TABLE #templist...
    

    【讨论】:

    • Msg 2714, Level 16, State 1, Line 25 数据库中已经有一个名为“#templist”的对象。
    【解决方案4】:

    是的。用完后放下桌子。 :)

    【讨论】:

    • 但他正在丢桌子……不是吗?
    • 是的。尝试了两种不同的方法。出于某种原因,当尝试在同一个脚本/会话中再次重新创建相同的临时表名称时,它总是给我发布的错误。
    • 是的,我自己也注意到了这一点。如果您在删除和重新创建之间在客户端中发出 GO,它将起作用。
    • @matt - 这不只是因为它重新初始化了您的连接吗?
    • @JNK 我不完全确定。这不像发出 GO 会破坏连接级临时表:SELECT 'test' AS test INTO #tmp/GO/SELECT * FROM #tmp 工作得很好。 (我不是在这里建议 GO 作为解决方案,只是想弄清楚到底发生了什么!)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 2017-10-07
    • 2020-11-18
    • 1970-01-01
    • 2011-02-24
    • 2019-04-14
    • 1970-01-01
    相关资源
    最近更新 更多