web-dev-qa-db-ja.com

ストアドプロシージャに一時テーブルが存在するかどうかを確認する必要がありますか?

一時テーブルを作成するだけでなく、ストアドプロシージャの開始時に明示的にチェック、削除、および作成することが推奨されるEdgeのケースはありますか?

同様に、SQL Serverにクリーンアップさせるよりも、ストアドプロシージャの最後に明示的にドロップした方がよい場合はありますか?

7
Akash

#tblのチェックについて

手順の最初でテーブルの存在を確認する(そして存在する場合は削除する)ことはできないが、それはそのシナリオを処理したい場合、ほとんどの場合、とにかくそれがすでに存在することは不可能です(少なくとも、sameについて話している場合は)#tempそのストアドプロシージャ内で定義されているテーブル)。

以下を使用して、テーブルの存在を確認します。

_IF OBJECT_ID('tempdb..#tablename') IS NOT NULL
_

Tempdb.sys.tablesをチェックすることはできません。実際の名前は_#tablename__________some hex code_であり、OBJECT_ID('...') > 0このため を使用しないでください。

もちろん、例外はあります。頭に浮かぶ2つ:

  • すべてを_#temp_、または_#t_、または_#x_を呼び出す場合、プロシージャを呼び出す前に、そのようなテーブルが外部スコープからすでに存在している可能性があります。ドロップして新しいケースを作成する必要がある場合もありますが、これが知りたいエラー状態である場合もあるため、_CREATE TABLE #x_が失敗してもかまいません。 。

  • 実際には、wantを使用して、外部スコープで作成された#tempテーブルを使用し、その外部スコープで定義されていない場合にのみテーブルを作成できます。これは可能であり、常にこの手法を使用していますが、通常は自分で簡単に操作できないシステムプロシージャからデータをキャプチャする場合にのみ(例:_sp_helptext_)。だから私はこれをするかもしれません:

    _CREATE TABLE #x([Text] NVARCHAR(MAX));
    GO
    CREATE PROCEDURE dbo.myhelp @p SYSNAME
    AS
      INSERT #x EXEC sp_helptext @p;
    GO
    EXEC dbo.myhelp N'dbo.myhelp'; -- inception
    GO
    SELECT [Text] FROM #x;
    _

    これは、_#x_が外部で定義されている場合でも機能します。 _sys.sql_modules_を使用したいので、これはひどい例ですが、ポイントを理解して、独自のプロシージャでそれを行う方法を想像できます。

DROP TABLE #tbl;

手順の最後に明示的に#tempテーブルを削除する必要があるかどうかは、議論の余地があるので、主に意見に基づくものとして閉じられます。 Paul White がこれらの優れたブログ投稿を確認し、よく読んで、すべての回答に回答しない場合は、戻って特定の質問を作成してください。

7
Aaron Bertrand

一時テーブルの使用方法に依存すると思います。 SELECT INTOが使用されている場合、前にテストし、最後にdropをテストします。事前にテストしてドロップすることで、忍び寄る可能性もそうでない可能性もある不要な問題を防ぐことができます。これは、私にとってはコードの実践に役立つだけです。

最初に一時テーブルを作成するためにCREATE TABLEを使用している場合は、習慣から外して同じ手順を実行し、手順を開発する方法について標準を維持しようと思います。これを使用すると、プロシージャの最後にdropステートメントを配置するだけで問題が解決され、最後にコードを削除するだけでコードを実行できます。

あなたがチームに属している場合、またはそれがあなただけの場合でも、標準を考え出してそれに固執してください。

2
user507