web-dev-qa-db-ja.com

DROP ... CREATEとALTER

ストアドプロシージャ、ビュー、関数などを作成する場合、オブジェクトに対してDROP ... CREATEまたはALTERを実行する方が良いですか?

DROP ... CREATEを実行することを述べた「標準」ドキュメントを数多く目にしましたが、ALTERメソッドを支持するコメントや議論を数多く目にしました。

ALTERメソッドはセキュリティを維持しますが、DROP ... CREATEメソッドは、ステートメントレベルの再コンパイルだけでなく、最初に実行されたときにSP全体を強制的に再コンパイルします。

どちらかを使用することに他の利点/欠点があるかどうか誰かに教えてもらえますか?

54
DCNYAM

ALTERはまた、プロシージャ全体の再コンパイルを強制します。ステートメントレベルの再コンパイルは、プロシージャ内のステートメントに適用されます。基になるテーブルが変更されたために再コンパイルされる単一のSELECT。プロシージャへの変更はありません。サーバーがそれをコンパイルする必要があるALTERプロシージャの後にSQLテキストで変更されたwhatを理解するために、ALTERプロシージャの特定のステートメントだけを選択的に再コンパイルすることさえ不可能です。

すべてのオブジェクトについて、ALTERはすべてのセキュリティ、すべての拡張プロパティ、すべての依存関係、およびすべての制約を保持するため、常に優れています。

49
Remus Rusanu

これは私たちのやり方です:

if object_id('YourSP') is null
    exec ('create procedure dbo.YourSP as select 1')
go
alter procedure dbo.YourSP
as
...

コードは、まだ存在しない場合は「スタブ」ストアドプロシージャを作成し、それ以外の場合は変更を行います。このようにして、スクリプトを繰り返し実行した場合でも、プロシージャに対する既存の権限は保持されます。

52
Andomar

変更することは一般的に良いです。ドロップして作成すると、そのオブジェクトに関連付けられている権限が失われる可能性があります。

8
kemiller2002

SQL Server 2016 SP1以降、CREATE OR ALTERストアドプロシージャ、関数、トリガー、ビューの構文。 SQL Serverデータベースエンジンブログの CREATE OR ALTER – SQL Server 2016 SP1のもう1つの優れた言語拡張 を参照してください。次に例を示します。

CREATE OR ALTER PROCEDURE dbo.MyProc
AS
BEGIN
    SELECT * FROM dbo.MyTable
END;
4
Dan Jagnow

たとえば、ウェブサイトから頻繁に呼び出される関数/ストアドプロシージャがある場合、問題が発生する可能性があります。

ストアドプロシージャは数ミリ秒/秒の間ドロップされ、その間、すべてのクエリは失敗します。

変更を行う場合、この問題はありません。

新しく作成されたストアドプロシージャのテンプレートは通常、次の形式です。

IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = '<name>')
    BEGIN
        DROP PROCEDURE <name>
    END
GO

CREATE PROCEDURE <name>
......

ただし、反対の方がいいです、imo:

Storedproc/function/etcが存在しない場合は、ダミーのselectステートメントで作成します。その後、変更は常に機能します-削除されることはありません。

そのためのストアドプロシージャがあるので、通常、ストアドプロシージャ/関数は次のようになります。

EXEC Utils.pAssureExistance 'Schema.pStoredProc'
GO

ALTER PROCECURE Schema.pStoredProc
...

関数には同じストアドプロシージャを使用します。

EXEC Utils.pAssureExistance 'Schema.fFunction'
GO

ALTER FUNCTION Schema.fFunction
...

Utils.pAssureExistanceでIFを実行し、 "。"の後の最初の文字を確認します。 "f"の場合はダミーのフォントを作成し、 "p"の場合はダミーのストアドプロシージャを作成します。

ただし、ダミーのスカラー関数を作成し、ALTERがテーブル値関数上にある場合、互換性がないというALTER FUNCTIONは失敗します。

繰り返しますが、Utils.pAssureExistanceは追加のオプションパラメータを使用すると便利です。

EXEC Utils.pAssureExistance 'Schema.fFunction', 'TableValuedFunction'

ダミーのテーブル値関数を作成し、

さらに、私は間違っているかもしれませんが、ドロッププロシージャを実行していて、クエリが現在ストアドプロシージャを使用している場合、失敗します。

ただし、変更プロシージャは、すべてのクエリがストアドプロシージャの使用を停止するのを待ってから、変更します。クエリがストアドプロシージャを長時間(たとえば、数秒)ロックしている場合、ALTERはロックの待機を停止し、とにかくストアドプロシージャを変更します。ストアドプロシージャを使用するクエリは、おそらくその時点で失敗します。

1
Kevin Doyon

[〜#〜] drop [〜#〜]を実行し、次に[〜#〜] create [〜#〜]を使用すると、ほぼALTER VIEWステートメントを使用するのと同じ効果。問題は、ビューを使用できるユーザーと使用できないユーザーのアクセス許可を完全に再確立する必要があることです。 [〜#〜] alter [〜#〜]依存関係情報を保持し、権限を設定します。

1
igelr

そのような全面的なコメントをして「ALTERの方がいい」と言えるのかどうかわかりません。状況次第だと思います。このようなきめ細かい権限を手順レベルまで必要とする場合は、おそらくこれを別の手順で処理する必要があります。ドロップして再作成することにはメリットがあります。既存のセキュリティを一掃し、予測可能なものをリセットします。

私は常にドロップ/再作成を使用することを好みました。また、それらをソース管理に格納する方が簡単だとわかりました。代わりに....存在する場合は変更し、存在しない場合は作成します。

とはいえ、あなたが何をしているのかわかっているなら...それほど重要ではないと思います。

1
sam yi

DROPは通常、権限と拡張プロパティを失います。

一部のUDFでは、ALTERも拡張プロパティを失います(SQL Server 2005マルチステートメントテーブル値関数では確実に)。

私は通常、DROPCREATEも、それらを再作成している(またはそれらを失いたいと思っている)場合を除き、しません。

0
Cade Roux

スクリプトをQAに移動するときに複数の環境がある場合、またはテストまたは製品にスクリプトがすでにその環境に存在するかどうかわからないため、存在する場合はドロップして追加することをお勧めします。ドロップを追加することで(既に存在する場合)、次に追加すると、ドロップが存在するかどうかに関係なくカバーされます。その後、アクセス許可を再適用する必要がありますが、インストールスクリプトがエラーになるのを聞くよりはましです。

0

データを含まないDBオブジェクトに特に関連する質問をしましたが、理論的にはそれほど頻繁に変更しないでください。

これらのオブジェクトを編集する必要がある可能性がありますが、5分ごとではありません。このため、あなたはすでにハンマーを頭にぶつけたと思います-許可。

短い回答、実際には問題ではありませんが、権限が問題でない限り

0
JL.

新しい機能の作成または機能の変更のいずれかを行っている開発中に、alterを使用していました。開発とテストが完了したら、ドロップアンドクリエイトを行います。これにより、プロシージャの日付/時刻スタンプが変更され、日付/時刻で並べ替えることができます。

また、発送した各成果物の日付ごとに何がバンドルされているかを確認することもできました。