Domanda

Come parte della mia strategia di integrazione, ho alcuni script SQL da eseguire per aggiornare il database.La prima cosa che fanno tutti questi script è verificare se devono essere eseguiti, ad esempio:

if @version <> @expects
    begin
        declare @error varchar(100);
        set @error = 'Invalid version. Your version is ' + convert(varchar, @version) + '. This script expects version ' + convert(varchar, @expects) + '.';
        raiserror(@error, 10, 1);
    end
else
    begin
        ...sql statements here...
    end

Funziona alla grande!Tranne se devo aggiungere una procedura memorizzata.Il comando "create proc" deve essere l'unico comando in un batch di comandi SQL.L'inserimento di un "create proc" nella mia istruzione IF provoca questo errore:

'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.

Ahia!Come posso inserire il comando CREATE PROC nel mio script e farlo eseguire solo se necessario?

È stato utile?

Soluzione

Ecco cosa mi è venuto in mente:

Avvolgilo in un EXEC(), in questo modo:

if @version <> @expects
    begin
        ...snip...
    end
else
    begin
        exec('CREATE PROC MyProc AS SELECT ''Victory!''');
    end

Funziona come un fascino!

Altri suggerimenti

SET NOEXEC ON è un buon modo per disattivare alcune parti del codice

IF NOT EXISTS (SELECT * FROM sys.assemblies WHERE name = 'SQL_CLR_Functions')
  SET NOEXEC ON
GO
CREATE FUNCTION dbo.CLR_CharList_Split(@list nvarchar(MAX), @delim nchar(1) = N',')
RETURNS TABLE (str nvarchar(4000)) AS EXTERNAL NAME SQL_CLR_Functions.[Granite.SQL.CLR.Functions].CLR_CharList_Split
GO
SET NOEXEC OFF

Trovato qui:https://codereview.stackexchange.com/questions/10490/conditional-create-must-be-the-only-statement-in-the-batch

PSUn altro modo è impostato parseonly {on | SPENTO }.

Ma fai attenzione alle virgolette singole all'interno della Stored Procedure: devono essere "escape" aggiungendone una seconda.La prima risposta ha fatto questo, ma nel caso te lo fossi perso.Una trappola per i giovani giocatori.

Versionare il database è la strada da percorrere, ma...Perché creare procedure memorizzate in modo condizionale.Per visualizzazioni, procedure memorizzate e funzioni, è sufficiente rilasciarle in modo condizionale e ricrearle ogni volta.Se crei in modo condizionale, non pulirai i database che presentano un problema o un hack inserito 2 anni fa da un altro sviluppatore (tu o io non lo faremmo mai) che era sicuro che si sarebbe ricordato di rimuovere l'unica volta aggiornamento di emergenza.

Il problema con l'eliminazione e la creazione è che si perdono eventuali concessioni di sicurezza precedentemente applicate all'oggetto eliminato.

Devo ammettere che normalmente sarei d'accordo con @Peter: lascio cadere condizionalmente e poi ricreano incondizionatamente ogni volta.Sono stato colto di sorpresa troppe volte in passato mentre cercavo di indovinare le differenze di schema tra i database, con o senza alcuna forma di controllo della versione.

Detto questo, il tuo suggerimento @Josh è davvero interessante.Certamente interessante.:-)

Questo è un vecchio thread, ma Jobo non è corretto:Crea procedura deve essere la prima istruzione in un batch.Pertanto non è possibile utilizzare Exists per testare l'esistenza e quindi utilizzare uno dei due Create O Alter.Pietà.

La mia soluzione è verificare se il proc esiste, in tal caso rilasciarlo e quindi creare il proc (stessa risposta di @robsoft ma con un esempio...)

IF EXISTS(SELECT * FROM sysobjects WHERE Name = 'PROC_NAME' AND xtype='P') 
BEGIN
    DROP PROCEDURE PROC_NAME
END
GO
CREATE PROCEDURE PROC_NAME
    @value  int
AS
BEGIN
    UPDATE  SomeTable
    SET     SomeColumn = 1
    WHERE   Value = @value
END
GO

utilizzare il comando "Esiste" in T-SQL per verificare se il processo memorizzato esiste.In tal caso, utilizza "Alter", altrimenti utilizza "Crea"

IF NOT EXISTS(SELECT * FROM sys.procedures WHERE name = 'pr_MyStoredProc')
BEGIN

     CREATE PROCEDURE pr_MyStoredProc AS .....
     SET NOCOUNT ON
END

ALTER PROC pr_MyStoredProc
AS
SELECT * FROM tb_MyTable
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top