差异

2012-11-05 81 views
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. 

此代码中表和临时表之间有什么区别?

+3

好问题。为了更好地说明你的观点[这个SQLFiddle](http://sqlfiddle.com/#!3/d41d8/5748)不起作用,但用普通表替换 – RichardTheKiwi

+4

[对行为的解释在这里](http: //sqlblog.com/blogs/michael_zilberstein/archive/2008/08/28/Name-resolution-in-SQL-Server.aspx)对于't1'语句可以延迟编译,但是对于'#' t1' –

+0

正如一边注意“[DROP TABLE和CREATE TABLE不应该在同一批次的同一张表上执行,否则可能会发生意外错误。](http://msdn.microsoft.com/zh-cn/库/ ms173790.aspx)“ –

回答

4

为了对抗其他所有的错误答案,来测试#TEMP表正确的方法是

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


下面是一个关于 interesting article编译阶段和执行阶段乐趣#TEMP表。


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

但是仍然有一些限制,如果名称确实存在,SQL Server将继续并检查语句的其他方面,例如表对象的列名称。 DNR从来没有扩展到变量或临时(#)/(##)对象,并且当在SQL Server 2000中添加了内联表值函数时,由于DNR的目的仅仅是解决multi - 语句批处理问题。不要混淆,内联表值函数不支持DNR; 多语句 TVFs。

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

-- 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; 
+0

它不起作用,我在这里问这里之前测试所有这些方法...... – NeatAttack

+0

@Neat如果你的意思是在没有'GO'的批处理的情况下,那么是的它不'解决编译时问题。我正在回答,因为所有其他测试都是错误的。 – RichardTheKiwi

+0

这里有什么合理的连接资源吗?我在网上看到的所有内容都表示,在连接重置时它们会被丢弃。 –