Come rilevare se esiste già una procedura memorizzata


Risposte:


160

Se DROP e CREATE la procedura, perderete le impostazioni di sicurezza. Ciò potrebbe infastidire il tuo DBA o interrompere completamente la tua applicazione.

Quello che faccio è creare una banale stored procedure se non esiste ancora. Successivamente, è possibile modificare la procedura memorizzata a proprio piacimento.

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

In questo modo, le impostazioni di sicurezza, i commenti e altri meta-deta sopravviveranno alla distribuzione.


2
Almeno se lo lasci cadere, sai che devi aggiungere nuovamente le autorizzazioni. Se avessi eseguito questo sql non sapresti se lo sproc avesse i permessi corretti o meno come non sapresti se l'hai creato o modificato.
Liazy,

@Liazy è la soluzione semplice per aggiungere il codice in if object_id('YourSp') is null BEGIN ... ENDper aggiungere le autorizzazioni appropriate dopo aver creato la procedura memorizzata.
Saluce,

4
pensa che l'altra risposta sia un po 'più completa in quanto estrae solo l'id oggetto per le stored procedure. non è comune avere lo stesso nome per tipi diversi ma potrebbe accadere
workabyte

149

Il modo più pulito è testarne l'esistenza, rilasciarlo se esiste e quindi ricrearlo. Non è possibile incorporare un'istruzione "create proc" in un'istruzione IF. Questo dovrebbe fare bene:

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

CREATE PROC MySproc
AS
BEGIN
    ...
END

1
Funzionerà, ma rimuove tutte le modifiche di sicurezza applicate alla procedura memorizzata.
Andomar,

18
Anche le modifiche alla sicurezza dovrebbero far parte degli script. In questo modo, verrà adeguatamente documentato. Questo è l'approccio giusto.
Ender Wiggin,

@EnderWiggin Tranne se l'implementazione della sicurezza non è nota in fase di progettazione ... Cosa succede se lo sviluppatore non sa quali utenti necessitano dei diritti di esecuzione?
Adriaan Davel,

2
@AdriaanDavel Ecco a cosa servono i DBA, e far parlare i DBA con gli sviluppatori si chiama gestione. Se sviluppatori e DBA non possono lavorare insieme, c'è un problema con l'azienda. Inoltre, i sistemi correttamente implementati non si basano sul privilegio dell'utente di toccare un database, ecco a cosa servono gli account di servizio e la sicurezza a livello di servizio dovrebbe essere applicabile a livello di database, in questo modo i DBA non devono spendere tempo e denaro per modificare la sicurezza sprocs individuali.
Shaun Wilson,

2
Non vorrei che gli sviluppatori abbandonassero / ricreassero sprocs che appartenevano a un prodotto commerciale. Vieni a pensarci bene, nemmeno i DBA lo faranno. Vedo che cosa stai ottenendo, tuttavia, ovvero "cosa succede se i DBA devono modificare la sicurezza in uno sproc post-distribuzione per un prodotto commerciale". Ribadirò che i sistemi correttamente implementati non si basano sui privilegi dell'utente e che la sicurezza a livello di servizio dovrebbe essere applicata a livello di database. Ho lavorato con DBA che si installeranno su un sistema demo / scratch e poi faranno un confronto dello schema per garantire che un aggiornamento sia sicuro, IMO questo è ciò che sono stati assunti per fare.
Shaun Wilson,

31

Se hai a che fare solo con stored procedure, la cosa più semplice da fare è probabilmente abbandonare il proc, quindi ricrearlo. È possibile generare tutto il codice per farlo utilizzando la procedura guidata Genera script in 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

Da SQL Server 2016 CTP3te puoi usare nuove istruzioni DIE invece di grandi IFwrapper

Sintassi:

DROP {PROC | PROCEDURA} [SE ESISTE] {[schema_name. ] procedura} [, ... n]

Query:

DROP PROCEDURE IF EXISTS usp_name

Maggiori informazioni qui


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

dov'è xxxil nome proc


4

Oltre a quanto è già stato detto, mi piace anche aggiungere un approccio diverso e sostenere l'uso della strategia di distribuzione degli script differenziali. Invece di creare uno script con stato che controlli sempre lo stato corrente e agisca in base a quello stato, distribuire tramite una serie di script senza stato che si aggiornano da versioni ben note . Ho usato questa strategia e ripaga alla grande in quanto i miei script di distribuzione sono ora tutti 'IF' gratuiti.


Interessante! Nei cinque anni da quando hai pubblicato questa risposta, ci sono stati ulteriori sviluppi nei metodi di controllo della versione del tuo database?
Thomas L Holaday,

4

È possibile scrivere una query come segue:

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

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

Per essere più specifici sulla sintassi sopra:
OBJECT_ID è un numero ID univoco per un oggetto all'interno del database, utilizzato internamente da SQL Server. Dato che stiamo passando ProcedureName seguito dal tuo tipo di oggetto P che dice a SQL Server che dovresti trovare l'oggetto chiamato ProcedureName che è di tipo procedure, cioè P

Questa query troverà la procedura e, se disponibile, la rilascerà e ne creerà una nuova.

Per informazioni dettagliate su OBJECT_ID e sui tipi di oggetto, visitare: SYS.Objects



0

Ho un proc memorizzato che consente al cliente di estendere la validazione, se esiste non voglio cambiarlo, se non lo voglio creare, il modo migliore che ho trovato:

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
Non ho fornito il voto negativo, ma, suppongo, direi che è stato votato verso il basso perché questa soluzione introduce nuove complicazioni con caratteri di citazione in fuga all'interno del corpo della procedura memorizzata.
donperk,

0

Il codice seguente controlla se la procedura memorizzata esiste già o meno.

Se esiste, cambierà, se non esiste creerà una nuova procedura memorizzata per te:

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

Un'opzione migliore potrebbe essere quella di utilizzare uno strumento come Red-Gate SQL Compare o SQL Examiner per confrontare automaticamente le differenze e generare uno script di migrazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.