为什么我不能在T-SQL中重复使用临时表?

4

以下是一些示例代码:

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可以在同一个连接下的不同查询中使用,您可以通过以##开头命名来声明全局临时表。 - adopilot
4个回答

6

变更

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 术语中的“编译”)。


1
我不知道为什么之前没有人回答,因为这是一个经典的例子,说明为什么/何时要使用GO。另一种避免错误的方法就是逐条执行语句。 - Gennady Vanin Геннадий Ванин
1
我不被允许在存储过程中编写GO,那么我该如何在SQL Server 2012中编写这个存储过程呢? - Imran Rizvi

5

对我来说,这似乎是一个解析器错误。我打赌它看到两个创建相同表的语句并抛出错误,无论有没有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

1

这是一个与作用域和#temp表有关的问题。由于可以使用相同命名的#temp表建立两个连接,因此元数据不直接按照您指定的名称引用它。

这篇博客文章中很详细地解释了这种行为。

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

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

Msg 2714,级别 16,状态 1,行 25 数据库中已经存在名为“#templist”的对象。 - MattB

-2

是的,使用完表格后请删除它。 :)


是的。我尝试了两种不同的方法。不知何故,在同一脚本/会话中再次尝试创建相同的临时表名称时,它总是提示错误。 - MattB
1
是的,我也注意到了这一点。如果在删除和重新创建之间在客户端中发出GO命令,它就会起作用。 - Matt Gibson
@matt - 这不仅是因为它重新初始化了您的连接吗? - JNK
@JNK 我不是完全确定。这不像发出一个GO会销毁连接级临时表:SELECT 'test' AS test INTO #tmp/GO/SELECT * FROM #tmp可以正常工作。(我不建议在这里使用GO作为解决方案,只是试图弄清楚到底发生了什么!) - Matt Gibson
看起来如果我在if object_id部分之前和之后都插入GO,那么问题就得到了解决。然后脚本就可以正常运行了。 - MattB
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接