web-dev-qa-db-ja.com

ストアドプロシージャが作成前に存在するかどうかを確認する方法

クライアントが「データベース管理」機能を実行するたびに実行する必要があるSQLスクリプトがあります。このスクリプトには、クライアントデータベースでストアドプロシージャを作成することが含まれています。これらのクライアントの中には、スクリプトの実行時にストアード・プロシージャーをすでに持っているものもあれば、そうでないものもあります。欠けているストアドプロシージャをクライアントデータベースに追加する必要がありますが、T-SQL構文をどれだけ曲げようとしても構いません。

CREATE/ALTER PROCEDURE 'は、クエリバッチの最初のステートメントでなければなりません

私は作品を作成する前にそれを落とすことを読みましたが、私はそのようにするのは好きではありません。

IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'MyProc')
DROP PROCEDURE MyProc
GO

CREATE PROCEDURE MyProc
...

ストアドプロシージャの存在の確認を追加し、存在しない場合は作成し、存在する場合は変更する方法を教えてください。

250
The Shaper

クエリを実行できる場所ならどこでも手続き型コードを実行できます。

ASの後にすべてをコピーするだけです。

BEGIN
    DECLARE @myvar INT
    SELECT  *
    FROM    mytable
    WHERE   @myvar ...
END

このコードは、ストアドプロシージャとまったく同じ動作をしますが、データベース側には格納されません。

これはPL/SQLで無名手続きと呼ばれるものとよく似ています。

更新:

あなたの質問のタイトルは少しわかりにくいです。

プロシージャが存在しない場合にのみプロシージャを作成する必要がある場合は、コードは問題ありません。

CreateスクリプトでSSMSが出力する内容は次のとおりです。

IF EXISTS ( SELECT  *
            FROM    sys.objects
            WHERE   object_id = OBJECT_ID(N'myproc')
                    AND type IN ( N'P', N'PC' ) ) 
DROP …
CREATE …

更新:

スキーマをインクルードするときの方法の例

IF EXISTS ( SELECT * 
            FROM   sysobjects 
            WHERE  id = object_id(N'[dbo].[MyProc]') 
                   and OBJECTPROPERTY(id, N'IsProcedure') = 1 )
BEGIN
    DROP PROCEDURE [dbo].[MyProc]
END

上記の例では、dboがスキーマです。

更新:

SQL Server 2016以降では、あなただけができる

CREATE OR ALTER PROCEDURE dbo.MyProc

167
Quassnoi

これはすでに回答済みとマークされていますが、以前は次のようにしていました。

IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND OBJECT_ID = OBJECT_ID('dbo.MyProc'))
   exec('CREATE PROCEDURE [dbo].[MyProc] AS BEGIN SET NOCOUNT ON; END')
GO

ALTER PROCEDURE [dbo].[MyProc] 
AS
  ....

手順を落とさないようにするためだけに。

428
Geoff

削除する前にデータベースオブジェクトの存在をチェックする最も簡単な方法を探しているのであれば、これが1つの方法です(上の例とまったく同じようにSPROCを使用しますが、テーブル、インデックスなどに変更できます)。

IF (OBJECT_ID('MyProcedure') IS NOT NULL)
  DROP PROCEDURE MyProcedure
GO

これは迅速でエレガントですが、それを考慮に入れていないため、すべてのオブジェクト・タイプにわたって固有のオブジェクト名があることを確認する必要があります。

私はこれが役立つことを願っています!

112
MrChips

「プロシージャが存在する場合は変更し、存在しない場合のみ削除する」ことをお勧めしますが、常にプロシージャを削除してから再作成するほうが簡単だと思います。プロシージャがすでに存在する場合にのみドロップする方法は次のとおりです。

IF OBJECT_ID('MyProcedure', 'P') IS NOT NULL
    DROP PROCEDURE MyProcedure
GO

2番目のパラメータは、 OBJECT_ID に、ストアドプロシージャであるobject_type = 'P'を持つオブジェクトのみを検索するように指示します。

AF =集約関数(CLR)

C = CHECK制約

D = DEFAULT(制約またはスタンドアロン)

F =外部キー制約

FN = SQLスカラー関数

FS =アセンブリ(CLR)スカラー関数

FT =アセンブリ(CLR)テーブル値関数

IF = SQLインライン表値関数

IT =内部テーブル

P = SQLストアドプロシージャ

PC =アセンブリ(CLR)ストアドプロシージャ

PG =プランガイド

PK = PRIMARY KEY制約

R =ルール(旧スタイル、スタンドアロン)

RF =複製フィルター手順

S =システムベーステーブル

SN =同義語

SO =シーケンスオブジェクト

TF = SQLテーブル値関数

次の方法でオプションの全リストを入手できます。

SELECT name 
FROM master..spt_values
WHERE type = 'O9T'
28
Michael Currie

SQL Server 2016以降、新しいDROP PROCEDURE IF EXISTSを使用できます。
DROP { PROC | PROCEDURE } [ IF EXISTS ] { [ schema_name. ] procedure } [ ,...n ]

参照: https://msdn.Microsoft.com/ja-jp/library/ms174969.aspx

20
Hybris95

これは非常に古い投稿ですが、これはトップの検索結果に表示されるため、SQL Server 2016 SP1を使用している人のための最新の更新を追加します -

create or alter procedure procTest
as
begin
 print (1)
end;
go

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

参考文献

17
gkb

私は同じエラーがありました。私はこのスレッドがすでにかなり死んでいることを知っていますが、「匿名手続き」以外に別のオプションを設定したいと思います。

私はこのように解決しました:

  1. ストアドプロシージャが存在するかどうかを確認します。

    IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='my_procedure') BEGIN
        print 'exists'  -- or watever you want
    END ELSE BEGIN
        print 'doesn''texists'   -- or watever you want
    END
    
  2. しかし"CREATE/ALTER PROCEDURE' must be the first statement in a query batch"はまだそこにあります。私はこのように解決しました:

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE -- view procedure function or anything you want ...
    
  3. 私はこのコードで終わります:

    IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID('my_procedure'))
    BEGIN
        DROP PROCEDURE my_procedure
    END
    
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE PROCEDURE [dbo].my_procedure ...
    
7
Oaxas

これがこのように使う方法とその背後にあるいくつかの推論です。ストアドプロシージャを編集するのはそれほどきれいではありませんが、長所と短所があります。

更新:この呼び出し全体をTRANSACTIONで囲むこともできます。すべてのコミットまたはすべてのロールバックが可能な単一のトランザクションに多数のストアドプロシージャを含める。トランザクションをラップするもう1つの利点は、READ UNCOMMITTEDトランザクション分離レベルを使用していない限り、ストアドプロシージャが他のSQL接続にも常に存在することです。

1)プロセスの決定として変更を避けるため。私たちのプロセスは、存在する場合は常に存在するIFを作成することです。新しいPROCが望ましいPROCであると想定するのと同じパターンを実行した場合、IF EXISTS ALTER ELSE CREATEがあるため、変更を提供することは少し難しくなります。

2)動的SQLの外側のトランザクションでプロシージャー更新のシーケンスをラップできないように、CREATE/ALTERを最初の呼び出しとしてバッチに入れる必要があります。基本的に、DBバックアップを復元せずにプロシージャー更新のスタック全体を実行したり、それらすべてをロールバックしたりしたい場合は、これをすべて1回のバッチで実行する方法です。

IF NOT EXISTS (select ss.name as SchemaName, sp.name as StoredProc 
    from sys.procedures sp
    join sys.schemas ss on sp.schema_id = ss.schema_id
    where ss.name = 'dbo' and sp.name = 'MyStoredProc')
BEGIN
    DECLARE @sql NVARCHAR(MAX)

    -- Not so aesthetically pleasing part. The actual proc definition is stored
    -- in our variable and then executed.
    SELECT @sql = 'CREATE PROCEDURE [dbo].[MyStoredProc]
(
@MyParam int
)
AS
SELECT @MyParam'
    EXEC sp_executesql @sql
END
5
Shiv

SQL Server 2008以降では、 "INFORMATION_SCHEMA.ROUTINES"を使用できます。

IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.ROUTINES 
  WHERE ROUTINE_NAME = 'MySP'
        AND ROUTINE_TYPE = 'PROCEDURE') 
4

DROP IF EXISTSはSQL Server 2016の新機能です。

https://blogs.msdn.Microsoft.com/sqlserverstorageengine/2015/11/03/drop-if-exists-new-thing-in-sql-server-2016/

DROP  PROCEDURE IF EXISTS dbo.[procname]
3
JayJay

投票やコメントに必要な評判は明らかにないのですが、EXECを使用したGeoffの回答(sp_executesqlのほうが良いかもしれません)が間違いなく有効な方法であると言いたいです。ストアドプロシージャを削除してから再作成すると、最終的にはジョブが完了しますが、ストアドプロシージャがまったく存在しない場合があります。繰り返し実行します。バックグラウンドスレッドがストアドプロシージャを使用しようとしていると同時にバックグラウンドスレッドがIF EXISTS DROP ... CREATEを実行していたため、私は自分のアプリケーションにさまざまな問題を抱えていました。

3
James

これが私が使うスクリプトです。それによって、私は不必要に保存されたprocを落として作り直すことを避けます。

IF NOT EXISTS (
    SELECT *
    FROM sys.objects
    WHERE object_id = OBJECT_ID(N'[dbo].[uspMyProcedure]')
    )
BEGIN
  EXEC sp_executesql N'CREATE PROCEDURE [dbo].[uspMyProcedure] AS select 1'
END
GO

ALTER PROCEDURE [dbo].[uspMyProcedure] 
    @variable1 INTEGER  
AS
BEGIN
   -- Stored procedure logic
END
3
myroslav

** T-Sqlでストアドプロシージャを削除して再作成する最も簡単な方法は**

Use DatabaseName
go
If Object_Id('schema.storedprocname') is not null
begin
   drop procedure schema.storedprocname
end
go

create procedure schema.storedprocname
as

begin
end
3
Rennish Joseph

ストアドプロシージャが存在するかどうかを確認

IF EXISTS (SELECT * FROM sys.objects 
            WHERE object_id = OBJECT_ID
             (N'[Schema].[Procedure_Name]') AND type IN (N'P', N'PC'))
BEGIN
       DROP PROCEDURE [Schema].[Procedure_Name]
       Print('Proceudre dropped => [Schema].[Procedure_Name]')
END

トリガーの下のIF Exist、機能もチェックしてください。

2
Jatin Phulera

なぜあなたはのような簡単な方法で行かないでください

    IF EXISTS(SELECT * FROM sys.procedures WHERE NAME LIKE 'uspBlackListGetAll')
    BEGIN
         DROP PROCEDURE uspBlackListGetAll
    END
    GO

    CREATE Procedure uspBlackListGetAll

..........

1
dnxit

私は疑問に思う!なぜ私は全体のクエリを書かないのですか

GO
create procedure [dbo].[spAddNewClass] @ClassName varchar(20),@ClassFee int
as
begin
insert into tblClass values (@ClassName,@ClassFee)
end

GO
create procedure [dbo].[spAddNewSection] @SectionName varchar(20),@ClassID       int
as
begin
insert into tblSection values(@SectionName,@ClassID)
end

Go
create procedure test
as
begin 
select * from tblstudent
end

私はすでに最初の2つの手続きが既に存在することを知っています。クライアント!

0

@ Geoff からの回答に加えて、ストアドプロシージャ、ビュー、関数、およびトリガ用のSQLファイルを生成する簡単なツールを作成しました。 。

MyDbUtils @ CodePlex を参照してください。 enter image description here

0
Stef Heyenrath