저장 프로 시저를 생성하기 전에 존재하는지 확인하는 방법


283

클라이언트가 "데이터베이스 관리"기능을 실행할 때마다 실행해야하는 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
...

저장 프로 시저의 존재 여부를 확인하고 존재하지 않는 경우 만들지 만 존재하는 경우 변경하려면 어떻게해야합니까?


2
그것은 작동하지 않습니다. 왜냐하면 그것이 원하는 것이 아닌 저장 프로 시저를 생성하기 때문입니다. 우리가 볼 수 있듯이, 완료 후에도 삭제되지 않으므로 용어의 모든 측면에 확실히 저장됩니다. 저장되지 않은 절차가 필요한 이유 는 중요 하지 않습니다
David Hedlund

'비 저장'절차의 의미는 무엇입니까? 샘플은 저장 프로 시저를 다시 작성하기 만하면됩니다. 이것이 당신의 질문과 어떤 관련이 있습니까?
AakashM

좋아, 우리는 간다. 문제는 많은 클라이언트가 사용하고 클라이언트가 소프트웨어가 제공하는 "데이터베이스 관리"기능을 실행할 때마다 철저히 실행해야하는 HUGE SQL 스크립트를 가지고 있다는 것입니다. 따라서 이러한 클라이언트 중 일부는 스크립트를 실행할 때 이미 프로 시저를 저장했을 수도 있고 그렇지 않을 수도 있습니다. 나는 이것이 어리 석다는 것을 알고 있습니다. 실제로 저장되지 않은 상태로 유지하기 위해이 절차가 필요하지 않습니다. 존재하는지 확인하고 존재하지 않는 경우 만들 수 있습니다. 그러나 T-SQL 구문을 얼마나 많이 구부리는지는 중요하지 않으며 항상 오류가 있습니다.
셰이퍼

스크립트를 실행할 때마다 프로 시저를 다시 작성하려고 시도합니다 (불행하게도, 프로 시저 작성 호출을 포함하여 모든 것을 동일한 .sql 파일에 스크립팅해야 함). 존재하지 않으면 구문 제한으로 인해 CREATE가 작동하지 않습니다. 어떡해?
셰이퍼

답변:


199

쿼리를 실행할 수있는 곳이면 절차 코드를 실행할 수 있습니다.

다음에 모든 것을 복사하십시오 AS.

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

이 코드는 저장 프로 시저가하는 것과 똑같은 작업을 수행하지만 데이터베이스쪽에는 저장되지 않습니다.

이는에서 익명 프로 시저라고하는 것과 매우 유사합니다 PL/SQL.

최신 정보:

질문 제목이 약간 혼동됩니다.

프로 시저가없는 경우에만 프로 시저를 작성해야하는 경우 코드는 정상입니다.

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


예, 이것은 사실이지만 프로 시저, udf, 뷰 등이 쿼리 내에서 호출하기 위해 저장되지 않으므로 모든 절차 기능을 잃게됩니다. (죄송합니다, 그것을 편집, 그것은 내 머리에 의미가 X-))
Adriaan Stander

1
예. 그러나 다른 프로 시저 내에서 프로 시저를 호출하거나 리턴 값을 테이블의 입력으로 사용할 수 있습니다.
Adriaan Stander

@astander: 저장 프로 시저에서 익명 코드를 호출 할 수도 있습니다. 에서 출력을 사용하려면 익명 코드와 함께 작동 하거나 작동 INSERT해야합니다 . 물론 익명 코드에는 단점이 있습니다. 예를 들어, 이는 호출자의 권한으로 만 실행됩니다. 내 요점은 그것이 일을하는 바람직한 방법이 아니라 가능하다는 것입니다 :)OPENROWSETOPENQUERY
Quassnoi

"프로 시저가 존재하지 않는 경우에만 프로 시저를 작성해야하는 경우 코드는 정상입니다." 그것이 바로 내가 알고 싶었던 것입니다. 실제 스크립트에서 SSMS Create to를 사용하려고 시도했지만 아무런 효과가 없었습니다. 그러나 Quassnoi에게 감사드립니다. 불분명 한 질문에 대해 죄송합니다.
셰이퍼

2
동적 SQL을 사용하지 않는 경우 CREATE PROC 문은 일괄 처리의 유일한 명령문이어야하므로이 방식으로 구현 될 때 DROP / CREATE를 둘러싼 트랜잭션을 랩핑 할 수 없습니다. DROP PROC 호출 후 GO (배치 구분 기호)가 있어야합니다.
Shiv

449

나는 이것이 이미 답변으로 표시되었음을 알고 있지만 다음과 같이 사용했습니다.

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
  ....

절차를 중단하지 않기 위해.


74
왜 이것이 좋은 아이디어인지에 대한 메모를 추가하기 위해 : 1) 드롭은 보안 설정을 지우고, 2) 이런 식으로 변경하면 어떤 이유로 스크립트가 실패하면 sp가 삭제되지 않습니다.
Ryan Guill 2013

10
이것이 정답입니다. 저장 프로 시저의 GRANTS가 손실되지 않도록합니다.
Andy_Vulhop

7
저장 프로 시저가 존재하지 않는 시점이 없다는 점에서이 방법에는 큰 이점이 있습니다. 다른 사람, 시스템 또는 스레드에서 여전히 업데이트를 사용하는 동안 중요 시스템에 업데이트를 적용하는 경우 중요 할 수 있습니다. 저장 프로 시저를 일시적으로 삭제하여 발생하는 오류를 추적하는 것은 재생산이 매우 어렵 기 때문에 매우 까다로울 수 있습니다.
James

3
이것은 이미 언급 한 여러 가지 이유로 훌륭한 솔루션이며 DBA가 proc 메타 데이터 (예 : 생성 날짜)에 의존하는 경우 proc를 만드는 대신 해당 항목을 그대로 둡니다. 매번 새로운 브랜드. 나는 이것을 우리 팀의 "우수 사례"로 바꾸려고 노력하고 있는데, 일반적으로 여러 DB에 복사 / 전파 해야하는 자체 프로세스를 유지 관리합니다.
NateJ

2
또한 어떤 사람들은 있다고 생각 합니다GRANT 스크립트의 문에 명시 적으로 그들이 변경할 경우를 ; 따라서 DROP대신에 사용 하는 것이 여전히 타당합니다 ALTER.
코디 스토트

123

데이터베이스 객체를 제거하기 전에 데이터베이스 객체의 존재를 확인하는 가장 간단한 방법을 찾고 있다면 여기에 한 가지 방법이 있습니다 (예는 위의 예와 같이 SPROC를 사용하지만 테이블, 인덱스 등을 위해 수정 될 수 있음).

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

이것은 빠르고 우아하지만 모든 객체 유형에 고유 한 객체 이름이 있는지 확인해야합니다.

이게 도움이 되길 바란다!


62
더 나은 : IF (OBJECT_ID ( 'MyProcedure', 'P')가 NULL이 아님) 삭제 절차 MyProcedure GO
alerya

33

"있는 경우 프로 시저를 변경하고 존재하지 않는 경우에만 삭제하십시오"를 원하지만 항상 프로 시저를 삭제 한 다음 다시 작성하는 것이 더 간단하다고 생각합니다. 프로 시저가 이미있는 경우에만 삭제하는 방법은 다음과 같습니다.

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

두 번째 매개 변수는 이야기 OBJECT_ID만을 가진 개체를보고 object_type = 'P', 저장하는 절차 :

AF = 집계 함수 (CLR)

C = 점검 제한 조건

D = DEFAULT (제약 또는 독립형)

F = 외래 키 제약

FN = SQL 스칼라 함수

FS = 어셈블리 (CLR) 스칼라 함수

FT = 어셈블리 (CLR) 테이블 반환 함수

IF = SQL 인라인 테이블 반환 함수

IT = 내부 테이블

P = SQL 저장 프로 시저

PC = 조립 (CLR) 저장 프로 시저

PG = 계획 가이드

PK = 기본 키 제약

R = 규칙 (구식, 독립형)

RF = 복제 필터 절차

S = 시스템 기본 테이블

SN = 동의어

SO = 시퀀스 객체

TF = SQL 테이블 반환 함수

TR = 트리거

다음을 통해 전체 옵션 목록을 얻을 수 있습니다.

SELECT name 
FROM master..spt_values
WHERE type = 'O9T'

1
TF가 없습니다.
여전히이

또한 트리거 TR
CarlosOro


23

나는 그것이 아주 오래된 게시물입니다 알지만, 따라서 사용하는 사람들을위한 최신 업데이트 추가 상단 검색 결과에서이 보이므로 SQL 서버 2016 SP1을 -

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

스토어드 프로 시저가없는 경우이를 작성하지만 존재하는 경우이를 변경합니다.

참고


1
이것은 매우 유용합니다.
AgentFire

SQL Studio에서만 작동한다는 것을 강조하고 싶습니다 .SQL 파일에서는 실패합니다.
James L.

10

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]

1
이것은 SqlServer 구문이 아닙니다 ... 사람들이 다운 투표를 시작하기 전에 답변을 제거하고 초보자에게 혼란을 피하는 조언입니다.
Pawel Czapski

@PawelCz는 SQL Server 2016 이상에서 유효합니다. 피드백 감사드립니다!
JayJay

이것은 원래 게시물에 대한 답변이 아닙니다. 자동으로 삭제하고 다시 만드는 것과 존재하지 않는 경우에만 만드는 것 사이에는 미묘한 차이가 있습니다. 프록을 삭제하면 스크립트와 관련된 보안이 삭제됩니다.
Ron

7

나는 같은 오류가 있었다. 이 스레드가 이미 죽었 음을 알고 있지만 "익명 절차"외에 다른 옵션을 설정하고 싶습니다.

나는 이것을 다음과 같이 해결했다.

  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 ...

이 DROP PROCEDURE과 같은 코드의 한 라인 ... 있다면 당신은 시작과 끝이 필요하지 않습니다
필립 SENN에게

경고 : '저장 프로 시저가 있는지 확인'기능은 어떤 함수 이름을 입력하든 (T-SQL의 경우) 항상 '존재'를 반환합니다. 신뢰할 수없는 검사입니다.
Ryan Battistone

더 나은 대안 : IF EXISTS (만약 sys.procedures에서 이름 1 '이름 _'name_of_table_as_seen_in_sysprocedures'에서 선택) BEGIN -1을 '상태'로 선택하십시오.
Ryan Battistone

5

이 방법을 사용하는 방법과 추론이 있습니다. 저장된 proc을 편집하는 것은 좋지 않지만 장단점이 있습니다 ...

업데이트 : 또한이 전체 전화를 거래로 포장 할 수 있습니다. 커밋 또는 롤백이 모두 가능한 단일 트랜잭션에 많은 저장 프로 시저 포함 트랜잭션 래핑의 또 다른 장점은 READ UNCOMMITTED 트랜잭션 격리 수준을 사용하지 않는 한 다른 SQL 연결에 대해 저장 프로 시저가 항상 존재한다는 것입니다!

1) 프로세스 결정과 같이 변경을 피하기 위해. 우리의 프로세스는 항상 존재한다면 삭제해야합니다. 새 PROC가 원하는 프로세스라고 가정하는 것과 동일한 패턴을 수행하는 경우 IF EXISTS ALTER ELSE CREATE가 있기 때문에 변경 사항을 처리하는 것이 약간 더 어렵습니다.

2) CREATE / ALTER를 배치의 첫 번째 호출로 배치해야하므로 동적 SQL 외부의 트랜잭션에서 일련의 프로 시저 업데이트를 래핑 할 수 없습니다. 기본적으로 DB 백업을 복원하지 않고 전체 프로 시저 업데이트 스택을 실행하거나 모두 롤백하려는 경우 단일 배치로 모든 작업을 수행 할 수 있습니다.

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

Sql Server 2008부터는 " INFORMATION_SCHEMA.ROUTINES"

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

3

나는 투표하거나 의견을 제시하는 데 필요한 명성을 얻지 못했지만 EXEC (sp_executesql이 더 좋을 수도 있음)를 사용하는 Geoff의 대답이 확실히 길이라고 말하고 싶었습니다. 저장 프로 시저를 삭제했다가 다시 만들면 결국 작업이 완료되지만 저장 프로 시저가 전혀 존재하지 않는 순간이 있습니다. 반복적으로 실행하십시오. 백그라운드 스레드가 IF EXISTS DROP ... CREATE를 수행하는 동시에 다른 스레드가 저장 프로 시저를 사용하려고했기 때문에 모든 종류의 응용 프로그램에 문제가있었습니다.


3

** 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

내가 사용하는 스크립트는 다음과 같습니다. 그것으로, 저장된 procs를 불필요하게 삭제하고 다시 만드는 것을 피합니다.

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


1

왜 간단한 방법으로 가지 않습니까?

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

    CREATE Procedure uspBlackListGetAll

..........


LIKE % 문을 사용하는 것은 좋지 않습니다. OP에 uspBlackListGetAll_V2와 같은 다른 sproc이 포함되어 있지 않다면 어떨까요?
Dave Hogan

@DaveHogan 동의합니다. 그러나 그는을 넣지 않았 %으므로 LIKE행동은 다음과 같이 작동합니다.=
Diego Jancic

1
@DiegoJancic 편집 한 기록을 보면 원래 기록이 '%'인 것을 알 수 있습니다.
Dave Hogan

0

@Geoff 의 답변 외에도 저장 프로 시저, 뷰, 함수 및 트리거에 대한 문을 SQL 파일로 생성하는 간단한 도구를 만들었습니다.

MyDbUtils @ CodePlex를 참조하십시오 . 여기에 이미지 설명을 입력하십시오


1
Management Studio는 이미 그러한 도구를 제공한다고 생각합니다. "스크립트를 생성합니다"라고
Hybris95

0

궁금하다! 왜 전체 쿼리를 작성하지 않습니까?

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

프로 시저 'Your proc-name'()이없는 경우 작성 프로 시저 ... 종료


절차가 존재하면 아무것도하지 않습니다. 요청자는 프로 시저가있는 경우 해당 프로 시저를 변경하려고합니다 (없는 경우).
랜디 Gamage
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.