Je génère un script pour migrer automatiquement les modifications de plusieurs bases de données de développement vers la préparation / production. Fondamentalement, cela prend un tas de scripts de changement et les fusionne en un seul script, enveloppant chaque script dans une IF whatever BEGIN ... END
instruction.
Cependant, certains scripts nécessitent une GO
instruction afin que, par exemple, l'analyseur SQL connaisse une nouvelle colonne après sa création.
ALTER TABLE dbo.EMPLOYEE
ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO -- Necessary, or next line will generate "Unknown column: EMP_IS_ADMIN"
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
Cependant, une fois que j'enroule cela dans un IF
bloc:
IF whatever
BEGIN
ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
END
Il échoue parce que j'envoie un BEGIN
sans correspondance END
. Cependant, si je supprime le, GO
il se plaint à nouveau d'une colonne inconnue.
Existe-t-il un moyen de créer et de mettre à jour la même colonne dans un seul IF
bloc?
sql
sql-server
tsql
sql-server-2008
BlueRaja - Danny Pflughoeft
la source
la source
GO
doit être sur une ligne par lui-même, vous pouvez donc rechercher uniquement ce cas, et pas toutes les instances du motGO
. 2) Vous pouvez toujours enregistrer les instructions qui ont été exécutées avec succès. Ou vous pouvez envelopper le tout dans un try / catch et utiliser vos propres numéros de ligne en utilisant une variable, comme @lineNo, dont vous gardez une trace et signalez l'erreur. Puisque vous les générez automatiquement, apporter des modifications comme celles-ci devrait être un jeu d'enfant. Il semble juste que vous ne vouliez pas explorer cette voie alors que je pense qu'il y a des solutions à trouver pour toutes vos préoccupations.Réponses:
J'ai eu le même problème et j'ai finalement réussi à le résoudre en utilisant SET NOEXEC .
la source
SQLCMD
script de mode SS (c'est-à-dire un script de déploiement principal) qui appelle (via une:r
commande) d'autres scripts SS (c'est-à-dire des scripts de sous-déploiement) avec certains de ces appels dans desif
déclarations. Les réponses d'Oded, de mellamokb et d'Andy Joiner qui ont inclus toutes ces déclarations dans lesexec
appels /begin
-end
ne sont pas des démarreurs. De plus, la méthodebegin
-end
ne fonctionnera pas s'il y a unecreate
déclaration (par exemple, elle nécessite un explicitego
avant). Mais, mec, "Saint doubles négatifs, Batman!" ;)if
), je préfixerais le bloc avec un-- If whatever
commentaire, mettrais en retrait le bloc et postfixerais le bloc avec un--end If whatever
commentaire.GO
n'est pas SQL - c'est simplement un séparateur de lots utilisé dans certains outils MS SQL.Si vous ne l'utilisez pas, vous devez vous assurer que les instructions sont exécutées séparément - soit dans différents lots ou en utilisant SQL dynamique pour la population (merci @gbn):
la source
IF
bloc.;
aide ici? - Vous venez de modifier votre réponse: o);
ne fonctionne pas non plus - l'analyseur me donne toujours "Nom de colonne non valide 'EMP_IS_ADMIN'."Vous pouvez essayer de
sp_executesql
diviser le contenu entre chaqueGO
instruction en une chaîne distincte à exécuter, comme illustré dans l'exemple ci-dessous. En outre, il existe une variable @statementNo pour suivre quelle instruction est exécutée pour un débogage facile là où une exception s'est produite. Les numéros de ligne seront relatifs au début du numéro de relevé pertinent qui a causé l'erreur.Vous pouvez également facilement exécuter des instructions multilignes, comme illustré dans l'exemple ci-dessus, en les entourant simplement de guillemets simples (
'
). N'oubliez pas d'échapper les guillemets simples contenus dans la chaîne avec un guillemet simple double (''
) lors de la génération des scripts.la source
SELECT * <newline> FROM whatever
. Si j'exécute chaque ligne avec sa propre instruction EXEC, cela va casser. Ou suggérez-vous que je m'interromps à chaqueGO
déclaration?J'ai finalement réussi à le faire fonctionner en remplaçant chaque instance de
GO
sur sa propre ligne parCeci est grandement préférable à l'encapsulation de chaque groupe d'instructions dans une chaîne, mais c'est encore loin d'être idéal. Si quelqu'un trouve une meilleure solution, postez-la et je l'accepterai à la place.
la source
IF
bloc). Il semble qu'il n'y ait tout simplement pas de bon moyen de faire cela en SQL.set noexec
réponse de Mina Jacob est la SEULE réponse pratique à ce jour à utiliser dans unSQLCMD
script de mode SS (c'est-à-dire un script de déploiement principal) qui appelle (via une:r
commande) d'autres scripts SS (c'est-à-dire des scripts de sous-déploiement) avec certains de ces appels dans desif
déclarations. Les réponses d'Oded, de mellamokb et d'Andy Joiner qui ont inclus toutes ces déclarations dans lesexec
appels /begin
-end
ne sont pas des démarreurs. De plus, la méthodebegin
-end
ne fonctionnera pas s'il y a unecreate
déclaration (par exemple, elle nécessite un explicitego
avant).Vous pouvez placer les instructions dans BEGIN et END au lieu de GO entre
(Testé sur la base de données Northwind)
Edit: (probablement testé sur SQL2012)
la source
set noexec
réponse de Mina Jacob est la SEULE réponse pratique à ce jour à utiliser dans unSQLCMD
script de mode SS (c'est-à-dire un script de déploiement principal) qui appelle (via une:r
commande) d'autres scripts SS (c'est-à-dire des scripts de sous-déploiement) avec certains de ces appels dans desif
déclarations. Les réponses d'Oded, de mellamokb et d'Andy Joiner qui ont inclus toutes ces déclarations dans lesexec
appels /begin
-end
ne sont pas des démarreurs. De plus, la méthodebegin
-end
ne fonctionnera pas s'il y a unecreate
déclaration (par exemple, elle nécessite un explicitego
avant).Vous pouvez essayer cette solution:
la source
J'ai utilisé
RAISERROR
dans le passé pour celala source
Vous pouvez incorporer des instructions
GOTO
etLABEL
pour sauter le code, laissant ainsi lesGO
mots - clés intacts.la source