ストアドプロシージャが既に存在するかどうかを検出する方法


130

ストアドプロシージャが存在するか存在しない場合に機能する展開スクリプトを作成する必要があります。つまり、存在する場合は変更する必要があります。それ以外の場合は作成します。

どうすればSQLでこれを行うことができますか?

SQL Server 2005を使用しています


回答:


160

プロシージャを削除して作成すると、セキュリティ設定が失われます。これは、DBAを困らせるか、アプリケーションを完全に破壊する可能性があります。

私がやっていることは、それがまだ存在しない場合、簡単なストアドプロシージャを作成することです。その後、必要に応じてストアドプロシージャを変更できます。

IF object_id('YourSp') IS NULL
    EXEC ('create procedure dbo.YourSp as select 1')
GO
ALTER PROCEDURE dbo.YourSp
AS
...

このようにして、セキュリティ設定、コメント、およびその他のメタデータは、展開後も存続します。


2
少なくとも、それをドロップした場合は、権限を再度追加する必要があることがわかります。このsqlを実行した場合、sprocが正しい権限を持っているかどうかは、作成または変更したかどうかわからないのでわかりません。
Liazy 2013年

@Liazyにはif object_id('YourSp') is null BEGIN ... END、ストアドプロシージャの作成後に適切なアクセス許可を追加するためのコードを追加するという簡単なソリューションがあります。
13

4
他の答えは、ストアドプロシージャのオブジェクトIDのみを取得するため、もう少し完全だと思います。異なるタイプに同じ名前を付けることは一般的ではありませんが、それが起こる可能性があります
workabyte

149

最もクリーンな方法は、その存在をテストし、存在する場合は削除してから再作成することです。IFステートメント内に「create proc」ステートメントを埋め込むことはできません。これはうまくいくはずです:

IF OBJECT_ID('MySproc', 'P') IS NOT NULL
DROP PROC MySproc
GO

CREATE PROC MySproc
AS
BEGIN
    ...
END

1
これは機能しますが、ストアドプロシージャに適用されたセキュリティの変更はすべて削除されます。
Andomar 2009年

18
セキュリティの変更もスクリプトの一部にする必要があります。そうすれば、適切に文書化されます。これが正しいアプローチです。
Ender Wiggin 2012年

@EnderWigginセキュリティの実装が設計時にわからない場合を除いて...開発者が実行権限を必要とするユーザーがわからない場合はどうなりますか?
Adriaan Davel 2013年

2
@AdriaanDavel lこれがDBAの目的であり、DBAが開発者と対話することを管理と呼びます。開発者とDBAが一緒に作業できない場合、会社に問題があります。さらに、適切に実装されたシステムは、データベースに触れるためのユーザー特権に依存しません。これがサービスアカウントの目的であり、サービスレベルのセキュリティはデータベース全体に適用できるため、DBAはセキュリティを微調整するために時間とお金を費やす必要がありません。個々のsproc。
Shaun Wilson、

2
商用製品に属するsprocをドロップ/再作成する開発者はいないでしょう。考えてみると、私もDBAがそうすることはないでしょう。ただし、「DBAが商用製品のsproc展開後のセキュリティを微調整する必要がある場合はどうなるか」ということはわかります。適切に実装されたシステムはユーザー特権に依存せず、サービスレベルのセキュリティはデータベース全体に適用する必要があることを繰り返し説明します。私はDBAと協力して、デモ/スクラッチシステムにインストールし、スキーマの比較を行ってアップグレードが安全であることを確認しました。
Shaun Wilson

31

ストアドプロシージャのみを扱う場合、最も簡単な方法は、おそらくプロシージャを削除してから再作成することです。SQL Serverのスクリプトの生成ウィザードを使用して、これを行うすべてのコードを生成できます。

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[YourSproc]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[YourSproc]

CREATE PROCEDURE YourSproc...

20

よりSQL Server 2016 CTP3新しい使用することができますDIEの 文の代わりに、大きなIFラッパを

構文:

DROP {PROC | 手順} [存在する場合] {[schema_name。]手順} [、... n]

クエリ:

DROP PROCEDURE IF EXISTS usp_name

詳細はこちら


11
if not exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[xxx]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
BEGIN
CREATE PROCEDURE dbo.xxx

xxxプロシージャ名はどこですか


4

すでに述べたことに加えて、私は別のアプローチを追加して、差分スクリプト展開戦略の使用を提唱することも好きです。常に現在の状態をチェックし、その状態に基づいて動作するステートフルスクリプトを作成する代わりに、既知のバージョンからアップグレードする一連のステートレススクリプトを介してデプロイします。私はこの戦略を使用しましたが、私の展開スクリプトはすべて「IF」フリーになっているので、大きなメリットがあります。


面白い!この回答を投稿してから5年間で、データベースのバージョン管理方法はさらに発展しましたか?
Thomas L Holaday、2014

4

クエリは次のように記述できます。

IF OBJECT_ID('ProcedureName','P') IS NOT NULL
    DROP PROC ProcedureName
GO

CREATE PROCEDURE [dbo].[ProcedureName]
...your query here....

上記の構文を具体的に説明すると、
OBJECT_IDはデータベース内のオブジェクトの一意のID番号であり、SQL Serverによって内部的に使用されます。ここでは、ProcedureNameの後にオブジェクトタイプPを渡しています。これは、タイプP、つまりPであるProcedureNameと呼ばれるオブジェクトを見つける必要があることをSQL Serverに伝えます。

このクエリはプロシージャを検索し、使用可能な場合はそれを削除して新しいプロシージャを作成します。

OBJECT_IDおよびオブジェクトタイプの詳細については、SYS.Objectsにアクセスしてください。



0

私は、顧客が検証を拡張できるストアドプロシージャを持っています。それが存在する場合、変更したくない場合、作成したくない場合、私が見つけた最良の方法です。

IF OBJECT_ID('ValidateRequestPost') IS NULL
BEGIN
    EXEC ('CREATE PROCEDURE ValidateRequestPost 
    @RequestNo VARCHAR(30),
    @ErrorStates VARCHAR(255) OUTPUT
AS
BEGIN
    SELECT @ErrorStates = @ErrorStates
END')
END

2
私は反対票を提供しませんでしたが、このソリューションは、ストアドプロシージャの本体内で引用符文字をエスケープするという新しい複雑さをもたらすため、おそらく反対票であったと言えます。
donperk

0

以下のコードは、ストアドプロシージャが既に存在するかどうかを確認します。

存在する場合は変更され、存在しない場合は新しいストアドプロシージャが作成されます。

//syntax for Create and Alter Proc 
DECLARE @Create NVARCHAR(200) = 'Create PROCEDURE sp_cp_test'; 
DECLARE @Alter NVARCHAR(200) ='Alter PROCEDURE sp_cp_test'; 
//Actual Procedure 
DECLARE @Proc NVARCHAR(200)= ' AS BEGIN select ''sh'' END'; 
//Checking For Sp
IF EXISTS (SELECT * 
           FROM   sysobjects 
           WHERE  id = Object_id('[dbo].[sp_cp_test]') 
                  AND Objectproperty(id, 'IsProcedure') = 1 
                  AND xtype = 'p' 
                  AND NAME = 'sp_cp_test') 
  BEGIN 
      SET @Proc=@Alter + @Proc 

      EXEC (@proc) 
  END 
ELSE 
  BEGIN 
      SET @Proc=@Create + @Proc 

      EXEC (@proc) 
  END 

go 

0

より適切なオプションは、Red-Gate SQL CompareやSQL Examinerなどのツールを使用して、違いを自動的に比較し、移行スクリプトを生成することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.