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 テーブルを使用したコンパイル フェーズと実行フェーズ の楽しみに関する興味深い記事です。


これは、 Deferred Name Resolution (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 に答える