2009-04-06 10 views
7

j'ai une situation où je veux vérifier une certaine colonne (comme le numéro de version), puis appliquer un groupe de ddl changeexécutant des instructions DDL conditionnelles sur le serveur SQL

problème est que je ne suis pas en mesure de le faire avec en un bloc IF BEGIN END, car les instructions DDL requièrent un séparateur GO entre elles, et TSQL ne le permet pas.

Je me demande s'il y a une façon d'y arriver autour

Répondre

0

GO est reconnu par les outils de client, et non par le serveur. Vous pouvez avoir des CREATE dans vos procédures stockées ou des requêtes ad-hoc sans GO.

1

Plusieurs instructions "IF"? Vous pouvez tester ensuite le succès des instructions DDL suivantes

Dynamic SQL? EXEC ('ALTER TABLE foo AVEC CHECK AJOUTER CONTRAINT ...')? Comme mentionné précédemment, GO est un séparateur de lots client uniquement pour décomposer un seul bloc de texte SQL en lots soumis à SQL Server.

+0

SQL dynamique deviendrait désordre très vite, puisque j'ai sql dynamique dans les procédures elles-mêmes –

+0

OK, plusieurs instructions IF puis ... – gbn

6

Vous n'avez pas besoin d'utiliser un bloc complet. Un conditionnel exécutera l'instruction suivante dans son intégralité si vous n'utilisez pas BEGIN/END - y compris une seule instruction DDL. Ceci est équivalent au comportement de si en Pascal, C, etc. Bien sûr, cela signifie que vous devrez revérifier votre état encore et encore et encore. Cela signifie également que l'utilisation de variables pour contrôler le comportement du script est pratiquement hors de question.

[Edit: CREATE PROCEDURE ne fonctionne pas dans l'exemple ci-dessous, donc je l'ai changé à quelque chose d'autre et déplacé CREATE PROCEDURE pour une plus longue discussion ci-dessous]

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 

... 

Ou quelque chose comme ça, en fonction de votre condition.

Malheureusement, CREATE/ALTER PROCEDURE et CREATE/ALTER VIEW ont des exigences particulières qui rendent le travail beaucoup plus difficile. Ils sont à peu près obligatoires pour être la seule chose dans une déclaration, donc vous ne pouvez pas les combiner avec IF du tout.

Pour de nombreux scénarios, quand vous voulez « mettre à jour » vos objets, vous pouvez travailler comme une baisse conditionnelle suivie d'une créer:

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 

Si vous avez vraiment besoin d'une logique conditionnelle de décider quoi faire , alors la seule façon que je connaisse est d'utiliser EXECUTE pour exécuter les instructions DDL sous forme de chaîne.

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

Mais c'est très douloureux. Vous devez échapper à toutes les citations dans le corps de la procédure et c'est vraiment difficile à lire. En fonction des modifications que vous devez appliquer, vous pouvez voir que tout cela peut devenir très laid rapidement. Ce qui précède ne comprend même pas la vérification des erreurs, qui est une douleur royale tout seul. C'est pourquoi des hordes d'outilleurs gagnent leur vie en trouvant des moyens d'automatiser la création de scripts de déploiement.

Désolé; il n'y a pas de "juste" moyen facile qui fonctionne pour tout. C'est juste quelque chose que TSQL supporte très mal. Pourtant, ce qui précède devrait être un bon début.

+0

Si ((SELECT Version FROM table WHERE ...) <= 15) CREATE PROCEDURE dbo.abc AS cette syntaxe ne fonctionnera pas .... il est dit Syntaxe incorrecte près du mot-clef 'PROCEDURE' –

+1

Vous avez raison! Pardon. Voir? Je vous ai dit que c'est désordonné (m'apprend à répondre à une question à 2h du matin). T-SQL nécessite que CREATE PROC soit l'instruction ONLY dans un "batch" (entre GO). J'ai corrigé l'exemple ci-dessus et vous ai fourni plus de détails sur le problème. Bonne chance. –

Questions connexes