Como detectar se um procedimento armazenado já existe

Respostas:

160

Se você soltar e criar o procedimento, perderá as configurações de segurança. Isso pode incomodar seu DBA ou interromper completamente seu aplicativo.

O que faço é criar um procedimento armazenado trivial, se ainda não existir. Depois disso, você pode ALTERAR o procedimento armazenado ao seu gosto.

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

Dessa forma, as configurações de segurança, os comentários e outras meta deta sobreviverão à implantação.

Andomar
fonte
2
Pelo menos, se você o soltar, você sabe que precisa adicionar novamente as permissões. Se você executou esse sql, não saberia se o sproc tinha as permissões corretas ou não, pois não saberia se o criou ou alterou.
Liazy
@Liazy, a solução simples que existe para adicionar código no if object_id('YourSp') is null BEGIN ... ENDpara adicionar as permissões apropriadas após a criação do procedimento armazenado.
saluce
4
pense que a outra resposta é um pouco mais completa, pois apenas puxa o ID do objeto para procedimentos armazenados. não é comum ter o mesmo nome para diferentes tipos, mas isso poderia acontecer
workabyte
149

A maneira mais limpa é testar sua existência, descartá-la, se existir, e depois recriá-la. Você não pode incorporar uma instrução "create proc" dentro de uma instrução IF. Isso deve fazer bem:

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

CREATE PROC MySproc
AS
BEGIN
    ...
END
Aaron Alton
fonte
1
Isso funcionará, mas remove as alterações de segurança aplicadas ao procedimento armazenado.
Andomar 02/06/2009
18
As alterações de segurança devem fazer parte dos scripts também. Dessa forma, ele será devidamente documentado. Essa é a abordagem correta.
Ender Wiggin
@EnderWiggin Exceto se a implementação de segurança não for conhecida no momento do design ... E se o desenvolvedor não souber quais usuários precisam executar direitos?
Adriaan Davel #
2
@AdriaanDavel l É para isso que servem os DBAs, e fazer com que os DBAs conversem com os desenvolvedores é chamado de gerenciamento. Se desenvolvedores e DBAs não podem trabalhar juntos, há um problema com a empresa. Além disso, os sistemas implementados corretamente não contam com o privilégio do usuário para tocar em um banco de dados, é para isso que servem as contas de serviço e a segurança do nível de serviço deve ser aplicável em todo o banco de dados, dessa forma os DBAs não precisam gastar tempo e dinheiro aprimorando a segurança em sprocs individuais.
Shaun Wilson
2
Eu não teria desenvolvedores lançando / recriando sprocs que pertenciam a um produto comercial. Venha para pensar sobre isso, eu também não teria DBAs fazendo isso. Eu vejo o que você está obtendo, no entanto, ou seja, "e se os DBAs precisarem ajustar a segurança em uma pós-implantação sproc para um produto comercial". Reiterarei que os sistemas implementados corretamente não dependem de privilégios de usuário e que a segurança no nível de serviço deve ser aplicada em todo o banco de dados. Trabalhei com DBAs que instalarão em um sistema de demonstração / rascunho e, em seguida, farão uma comparação de esquema para garantir que uma atualização seja segura; IMO é para isso que eles são contratados.
Shaun Wilson
31

Se você estiver lidando apenas com procedimentos armazenados, a coisa mais fácil a fazer é provavelmente largar o proc e depois recriá-lo. Você pode gerar todo o código para fazer isso usando o assistente para gerar scripts no 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...
JasonS
fonte
20

Desde SQL Server 2016 CTP3que você pode usar novas DIE declarações em vez de grandes IFembalagens

Sintaxe:

GOTA {PROC | PROCEDIMENTO} [SE EXISTE] {[schema_name. ] procedimento} [, ... n]

Inquerir:

DROP PROCEDURE IF EXISTS usp_name

Mais informações aqui

P ரதீப்
fonte
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

onde xxxé o nome do proc

Luke Schafer
fonte
4

Além do que já foi dito, também gosto de adicionar uma abordagem diferente e advogar o uso da estratégia de implantação de scripts diferenciais. Em vez de criar um script com estado que sempre verifique o estado atual e atue com base nesse estado, implante por meio de uma série de scripts sem estado que são atualizados a partir de versões conhecidas . Eu usei essa estratégia e vale muito a pena, pois meus scripts de implantação agora estão todos 'SE' livres.

Remus Rusanu
fonte
Interessante! Nos cinco anos desde que você postou esta resposta, houve mais desenvolvimentos nos métodos de controle de versão do banco de dados?
Thomas L Holaday
4

Você pode escrever uma consulta da seguinte maneira:

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

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

Para ser mais específico na sintaxe acima:
OBJECT_ID é um número de identificação exclusivo para um objeto no banco de dados, usado internamente pelo SQL Server. Como estamos passando o ProcedureName seguido pelo seu tipo de objeto P, que informa ao SQL Server que você deve encontrar o objeto chamado ProcedureName, que é do tipo procedure, ou seja, P

Esta consulta encontrará o procedimento e, se estiver disponível, descartará e criará um novo.

Para informações detalhadas sobre OBJECT_ID e tipos de objeto, visite: SYS.Objects

shary.sharath
fonte
3
IF OBJECT_ID('SPNAME') IS NULL
     -- Does Not Exists
ELSE
     -- Exists
Hemanshu Bhojak
fonte
0

Eu tenho um procedimento armazenado que permite ao cliente estender a validação; se existir, não quero alterá-lo; se não, quero criá-lo, da melhor maneira que encontrei:

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
Adriaan Davel
fonte
2
Eu não forneço o voto negativo, mas, suponho, eu diria que ele foi rejeitado porque esta solução introduz novas complicações com caracteres de aspas vazios no corpo do procedimento armazenado.
318 donperk
0

O código abaixo verificará se o procedimento armazenado já existe ou não.

Se existir, ele será alterado, se não existir, criará um novo procedimento armazenado para você:

//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 
shiva kumar kella
fonte
0

Uma opção melhor pode ser usar uma ferramenta como o Red-Gate SQL Compare ou o SQL Examiner para comparar automaticamente as diferenças e gerar um script de migração.

Kane
fonte