データのサブセットのインタラクティブな分析に使用されるスクリプトでは、クエリの結果を一時テーブルに保存して、さらに分析できるようにすると便利なことがよくあります。
私の分析スクリプトの多くには、次の構造が含まれています。
CREATE TABLE #Results (
a INT NOT NULL,
b INT NOT NULL,
c INT NOT NULL
);
INSERT INTO #Results (a, b, c)
SELECT a, b, c
FROM ...
SELECT *
FROM #Results;
SQL Server では、一時テーブルは接続スコープであるため、クエリの結果は最初のクエリの実行後も保持されます。分析したいデータのサブセットの計算にコストがかかる場合、テーブル変数を使用する代わりにこの方法を使用します。これは、サブセットがクエリのさまざまなバッチ間で保持されるためです。
スクリプトのセットアップ部分は 1 回実行され、次のクエリ (SELECT * FROM #Results
はプレースホルダーです) が必要なだけ実行されます。
時々、一時テーブルのデータのサブセットを更新したいので、スクリプト全体をもう一度実行します。これを行う 1 つの方法は、Management Studio の新しいクエリ ウィンドウにスクリプトをコピーして新しい接続を作成することですが、これは管理が難しいと思います。
代わりに、私の通常の回避策は、次のような条件付きドロップ ステートメントを作成ステートメントの前に置くことです。
IF OBJECT_ID(N'tempdb.dbo.#Results', 'U') IS NOT NULL
BEGIN
DROP TABLE #Results;
END;
このステートメントは、次の 2 つの状況を正しく処理します。
- テーブルが存在しない最初の実行時: 何もしません。
- テーブルが存在する場合の後続の実行時: テーブルを削除します。
私が作成したプロダクション スクリプトでは、2 つの予想される状況でエラーが発生しないため、常にこの方法を使用します。
私の仲間の開発者によって書かれたいくつかの同等のスクリプトは、例外処理を使用してこれら 2 つの状況を処理することがあります。
BEGIN TRY DROP TABLE #Results END TRY BEGIN CATCH END CATCH
データベースの世界では、許しを求めるよりも常に許可を求める方が良いと信じているため、この方法は不安になります。
2 番目の方法は、例外的でない動作 (テーブルが存在しない) を処理するためのアクションを実行せずに、エラーを飲み込みます。また、テーブルが存在しない以外の理由でエラーが発生する可能性もあります。
賢明なフクロウは同じことについて警告しています:
2 つの方法のうち、[
OBJECT_ID
method] の方が理解しにくいですが、おそらくより優れています。[BEGIN TRY
method] を使用すると、間違ったエラーをトラップするリスクがあります。
しかし、実際のリスクが何であるかは説明されていません。
実際には、BEGIN TRY
私が保守しているシステムでこの方法が問題を引き起こしたことは一度もないので、そのままにしておいてよかったと思っています。
BEGIN TRY
メソッドを使用して一時テーブルの存在を管理する場合、どのような危険が考えられますか? 空の catch ブロックによって隠される可能性のある予期しないエラーは何ですか?