差異

2012-11-05 125 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

這裏有什麼合理的連接資源嗎?我在網上看到的所有內容都表示,在連接重置時它們會被丟棄。 –