7

为什么这段代码可以正常工作:

drop table t1 
select * into t1 from  master..spt_values
drop table t1 
select * into t1 from  master..spt_values

输出

Msg 3701, Level 11, State 5, Line 1
Cannot drop the table 't1', because it does not exist or you do not have permission.

(2508 row(s) affected)

(2508 row(s) affected)

但这段代码没有:

drop table #t1 
select * into #t1 from  master..spt_values
drop table #t1 
select * into #t1 from  master..spt_values

输出

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

这段代码中的表和临时表有什么区别?

4

1 回答 1

4

为了反驳所有其他错误答案,测试#temp 表的正确方法是

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


这是一篇关于#temp 表的编译阶段和执行阶段乐趣的有趣文章。


这是延迟名称解析(DNR) 的 MSDN 参考。为了帮助存储过程创建和语句批处理,Deferred Name Resolution在 SQL Server 7 中添加了。在此之前(Sybase),如果不使用大量动态 SQL,在批处理中创建和使用表将非常困难。

但是仍然存在限制,如果名称确实存在,SQL Server 将继续检查语句的其他方面,例如表对象的列名。DNR 从未扩展到变量或临时 (#)/(##) 对象,当 SQL Server 2000 中添加内联表值函数时,DNR 也没有扩展到它们,因为 DNR 的目的只是解决多-语句批处理问题。不要混淆,内联表值函数不支持 DNR;多语句TVF 可以。

解决方法是不使用该模式,而是先创建表,并且只创建一次。

-- drop if exists
if object_id('tempdb..#t1') is not null
   drop table #t1; 
-- create table ONCE only
select * into #t1 from master..spt_values where 1=0;
-- .... 
-- populate
insert #t1
select * from master..spt_values
-- as quick as drop
truncate table #t1; 
-- populate
insert #t1
select * from master..spt_values
-- as quick as drop
truncate table #t1; 

-- clean up
drop table #t1; 
于 2012-11-05T10:33:10.747 回答