2009-04-06 14 views
7

Ho una situazione in cui voglio controllare una determinata colonna (come numero di versione) e quindi applicare un po 'di DDL cambiache eseguono istruzioni DDL condizionali su sql server

guaio è che non sono in grado di farlo con in un blocco IF BEGIN END, poiché le istruzioni DDL richiedono un separatore GO tra di loro e TSQL non lo consentirà.

Mi chiedo se non v'è alcun modo per aggirare per raggiungere questo obiettivo

risposta

0

GO è riconosciuto da strumenti client, non dal server. È possibile avere CREATE nelle stored procedure o query ad-hoc senza GO.

1

Più dichiarazioni "IF"? È possibile testare quindi per il successo delle successive istruzioni DDL

SQL dinamico? EXEC ('ALTER TABLE foo WITH CHECK ADD CONSTRAINT ...')?

Come accennato, GO è un separatore di batch solo client per suddividere un singolo blocco di testo SQL in batch inviati a SQL Server.

+0

SQL dinamico sarebbe diventato disordinato molto presto, dal momento che ho SQL dinamico all'interno delle procedure stesse –

+0

OK, multipla IF THEN ... – gbn

6

Non è necessario utilizzare un blocco completo. Un condizionale eseguirà l'istruzione successiva nella sua interezza se non si utilizza un BEGIN/END, inclusa una singola istruzione DDL. Questo è equivalente al comportamento di se in Pascal, C, ecc. Ovviamente, ciò significa che dovrai ricontrollare le tue condizioni più e più volte. Significa anche che l'utilizzo di variabili per controllare il comportamento dello script è praticamente fuori questione.

[Edit: CREATE PROCEDURE non funziona nell'esempio qui sotto, quindi l'ho cambiato a qualcosa d'altro e si trasferisce CREATE PROCEDURE per una discussione più estesa sotto]

If ((SELECT Version FROM table WHERE...) <= 15) 
CREATE TABLE dbo.MNP (
.... 
) 
GO 

If ((SELECT Version FROM table WHERE...) <= 15) 
ALTER TABLE dbo.T1 
ALTER COLUMN Field1 AS CHAR(15) 
GO 

... 

O qualcosa del genere, a seconda di quale sia la tua condizione.

Sfortunatamente, CREATE/ALTER PROCEDURE e CREATE/ALTER VIEW hanno requisiti speciali che rendono molto più difficile lavorare con. Sono praticamente obbligati a essere l'unica cosa in una dichiarazione, quindi non è possibile combinarli con IF.

Per molti scenari, quando si vuole "aggiornare" gli oggetti, si può lavorare come una goccia condizionale seguito da un creare:

IF(EXISTS(SELECT * FROM sys.objects WHERE type='p' AND object_id = OBJECT_ID('dbo.abc'))) 
DROP PROCEDURE dbo.abc 
GO 

CREATE PROCEDURE dbo.abc 
AS 
    ... 
GO 

Se si ha realmente bisogno la logica condizionale per decidere cosa fare , quindi l'unico modo che conosco è usare EXECUTE per eseguire le istruzioni DDL come una stringa.

If ((SELECT Version FROM table WHERE...) <= 15) 
EXECUTE 'CREATE PROC dbo.abc 
AS 
    .... 
') 

Ma questo è molto doloroso. Devi sfuggire a qualsiasi citazione nel corpo della procedura ed è davvero difficile da leggere.

A seconda delle modifiche che è necessario applicare, è possibile vedere tutto questo può diventare molto brutto veloce. Quanto sopra non include nemmeno il controllo degli errori, che è un dolore reale tutto da solo. Questo è il motivo per cui orde di produttori di utensili si guadagnano da vivere cercando di capire come automatizzare la creazione di script di implementazione.

Siamo spiacenti; non esiste un modo "giusto" facile che funzioni per tutto. Questo è solo qualcosa che TSQL supporta molto male. Tuttavia, quanto sopra dovrebbe essere un buon inizio.

+0

Se ((SELECT versione FROM tabella WHERE ...) <= 15) Create Procedure dbo.abc AS questa sintassi non funzionerà .... si dice sintassi errata vicino alla parola chiave 'PROCEDURA' –

+1

Sei corretto! Scusate. Vedere? Ti ho detto che è disordinato (mi insegna di rispondere a una domanda alle 2). T-SQL richiede CREATE PROC per essere l'unica dichiarazione in un "batch" (tra GO). Ho corretto l'esempio sopra e ti ho fornito maggiori dettagli sul problema. In bocca al lupo. –

Problemi correlati