数据库中已经存在一个名为“##Temp”的对象。

14

我在 SQL Server 2000 上有一个存储过程,它包含以下内容:
select ... into ##Temp ...
...
drop table ##Temp

当我用 ADO 运行这个存储过程第二次时,它会提示:
数据库中已经存在名为 '##Temp' 的对象。
请问这是什么问题?


你能不能只使用一个表变量(select .. into @temp)?这样你就不需要担心释放表等问题了。 - RPM1984
表结构是动态的。这就是为什么我使用临时表的原因。 - phoenies
5个回答

26

你应该重写存储过程,如果存在临时表,则删除它,这样就永远不会遇到这个问题。

IF (SELECT object_id('TempDB..##Temp')) IS NOT NULL
BEGIN
    DROP TABLE ##Temp
END

错误信息为<数据库中已经存在名为'##Temp'的对象>,问题出在<select ... into ##Temp ...>而不是<DROP TABLE ##Temp>。 - gyromonotron
2
是的,如果已经有一个名为##Temp的对象,您需要删除原始对象才能创建新对象... - Jon Freedman
只是出于好奇,这段代码只适用于SQL-Server 2000吗?我在SQL-Server 2008中尝试了一下,但是出现了错误:“无法删除表'#jobsconsumed',因为它不存在或您没有权限。” - whatwhatwhat
我曾经在脚本范围内运行object_id测试失败,但当你突出显示然后执行所有代码时,它会通过。IS_OBJECT似乎不是易失性的;它似乎记录了脚本执行开始时的状态,并以不同的方式记录突出显示然后执行时的状态。 - Jessica Pennell

1

您正在使用全局临时表,这是由表名开头的 ## 标识的。这意味着多个会话可以访问该表。

很可能您有一个打开连接创建了该表,但未能删除它。您确定第一个 ADO 运行实际删除了该表吗?可能失败了,或者过程中的流程控制跳过了删除语句吗?

您可能需要在 SQL Server Enterprise Manager 中测试该过程,以查看是否报告任何错误。


我也无法从查询分析器中删除它。也许前几次出了什么问题。我会再试一下。 - phoenies
是的,我应该提到只有创建连接可以关闭它。你可以运行SP_WHO2来查看是否有其他可能是所有者的连接。不幸的是,它无法告诉你哪个连接拥有该文件。祝好运。 - bobs

1

由于您选择使用全局临时表##Temp,因此它在任何给定时间都对所有SQL连接可见。显然,在一个连接的存储过程运行时,第二个连接进来并尝试创建另一个##Temp,但已经存在....

改用连接本地的#Temp表(只有一个#)。


额...但我确定只有一个连接Private DBCon As New Connection,这是我创建的。 - phoenies

1

哦,这都是我的错。我不小心通过一个连接调用了SP两次。
这就是为什么第二次调用它时总是报错的原因。
当然,你读完我的描述也不会知道这一点。对不起,大家……


0

对我来说,这个解决方案有效:

IF (SELECT object_id ='#Temp') IS NOT NULL
BEGIN
   DROP TABLE #Temp
END

1
那样行不通。object_id是一个函数。应该写成object_id('#temp') - Dave R.

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