Ich generiere ein Skript für die automatische Migration von Änderungen aus mehreren Entwicklungsdatenbanken zu Staging / Produktion. Grundsätzlich werden eine Reihe von Änderungsskripten benötigt, die zu einem einzigen Skript zusammengeführt werden, wobei jedes Skript in eine IF whatever BEGIN ... END
Anweisung eingeschlossen wird.
Einige der Skripte erfordern jedoch eine GO
Anweisung, damit der SQL-Parser beispielsweise nach der Erstellung eine neue Spalte kennt.
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
Sobald ich das jedoch in einen IF
Block einpacke:
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
Es schlägt fehl, weil ich eine BEGIN
ohne Übereinstimmung sende END
. Wenn ich das jedoch entferne GO
, beschwert es sich erneut über eine unbekannte Spalte.
Gibt es eine Möglichkeit, dieselbe Spalte in einem einzelnen IF
Block zu erstellen und zu aktualisieren ?
quelle
GO
, es muss eine eigene Zeile sein, damit Sie nur nach diesem Fall suchen können und nicht nach jeder Instanz des WortesGO
. 2) Sie können jederzeit protokollieren, welche Anweisungen erfolgreich abgeschlossen wurden. Oder Sie können das Ganze in einen Versuch / Fang einwickeln und Ihre eigenen Zeilennummern mit einer Variablen wie @lineNo verwenden, die Sie verfolgen und über Fehler berichten. Da Sie diese automatisch generieren, sollten Änderungen wie diese ein Kinderspiel sein. Es hört sich einfach so an, als ob Sie diese Route einfach nicht erkunden möchten, wenn ich denke, dass es Lösungen für all Ihre Anliegen gibt.Antworten:
GO
ist kein SQL - es ist einfach ein Batch-Trennzeichen, das in einigen MS SQL-Tools verwendet wird.Wenn Sie dies nicht verwenden, müssen Sie sicherstellen, dass die Anweisungen separat ausgeführt werden - entweder in verschiedenen Stapeln oder mithilfe von dynamischem SQL für die Grundgesamtheit (danke @gbn):
quelle
IF
Block erstellen und aktualisieren .;
hier raushelfen ? - Sie haben gerade Ihre Antwort bearbeitet: o);
funktioniert auch nicht - der Parser gibt mir immer noch "Ungültiger Spaltenname 'EMP_IS_ADMIN'".Ich hatte das gleiche Problem und konnte es schließlich mit SET NOEXEC lösen .
quelle
SQLCMD
Modus-Skript (dh einem Master-Bereitstellungsskript), das (über einen:r
Befehl) andere SS-Skripte (dh Unterbereitstellungsskripte) mit einigen dieser Aufrufe inif
Anweisungen aufruft . Die Antworten von Oded, Mellamokb und Andy Joiner, alle diese Aussagen inexec
Calls /begin
- aufzunehmenend
, sind keine Starter. Außerdem funktioniert diebegin
-end
-Methode nicht, wenn einecreate
Anweisung vorhanden ist (z. B. erfordert eine explizite Anweisunggo
davor). Aber Mann, "Heilige Doppel-Negative, Batman!" ;)if
Block simuliert wird ) würde ich dem Block einen-- If whatever
Kommentar voranstellen, den Block einrücken und den Block mit einem--end If whatever
Kommentar nachfixieren.Sie können versuchen
sp_executesql
, den Inhalt zwischen den einzelnenGO
Anweisungen in eine separate auszuführende Zeichenfolge aufzuteilen, wie im folgenden Beispiel gezeigt. Außerdem gibt es eine Variable @statementNo, mit der verfolgt werden kann, welche Anweisung zum einfachen Debuggen ausgeführt wird, wenn eine Ausnahme aufgetreten ist. Die Zeilennummern beziehen sich auf den Anfang der entsprechenden Anweisungsnummer, die den Fehler verursacht hat.Sie können auch einfach mehrzeilige Anweisungen ausführen, wie im obigen Beispiel gezeigt, indem Sie sie einfach in einfache Anführungszeichen (
'
) setzen. Vergessen Sie nicht,''
beim Erstellen der Skripte einfache Anführungszeichen in der Zeichenfolge mit einem doppelten einfachen Anführungszeichen ( ) zu umgehen.quelle
SELECT * <newline> FROM whatever
. Wenn ich jede Zeile mit einer eigenen EXEC-Anweisung ausführe, wird dies unterbrochen. Oder schlagen Sie vor, dass ich bei jederGO
Aussage breche ?Ich habe es letztendlich zum Laufen gebracht, indem ich jede Instanz
GO
auf ihrer eigenen Linie durch ersetzt habeDies ist stark bevorzugt , jede Gruppe von Anweisungen in einer Zeichenfolge zu wickeln, ist aber noch weit vom Ideal entfernt . Wenn jemand eine bessere Lösung findet, poste sie und ich akzeptiere sie stattdessen.
quelle
IF
Blocks hinzugefügt wird ). Es scheint, als gäbe es in SQL einfach keinen guten Weg, dies zu tun.set noexec
Antwort von Mina Jacob ist die bislang EINZIGE praktische Antwort für die Verwendung in einem SS-SQLCMD
Modus-Skript (dh einem Master-Bereitstellungsskript), das (über einen:r
Befehl) andere SS-Skripte (dh Unterbereitstellungsskripte) mit einigen dieser Aufrufe inif
Anweisungen aufruft . Die Antworten von Oded, Mellamokb und Andy Joiner, alle diese Aussagen inexec
Calls /begin
- aufzunehmenend
, sind keine Starter. Außerdem funktioniert diebegin
-end
-Methode nicht, wenn einecreate
Anweisung vorhanden ist (z. B. erfordert eine explizite Anweisunggo
davor).Sie können die Anweisungen in BEGIN und END anstelle des GO dazwischen einschließen
(Getestet in der Northwind-Datenbank)
Bearbeiten: (wahrscheinlich auf SQL2012 getestet)
quelle
set noexec
Antwort von Mina Jacob ist die bislang EINZIGE praktische Antwort für die Verwendung in einem SS-SQLCMD
Modus-Skript (dh einem Master-Bereitstellungsskript), das (über einen:r
Befehl) andere SS-Skripte (dh Unterbereitstellungsskripte) mit einigen dieser Aufrufe inif
Anweisungen aufruft . Die Antworten von Oded, Mellamokb und Andy Joiner, alle diese Aussagen inexec
Calls /begin
- aufzunehmenend
, sind keine Starter. Außerdem funktioniert diebegin
-end
-Methode nicht, wenn einecreate
Anweisung vorhanden ist (z. B. erfordert eine explizite Anweisunggo
davor).Sie können diese Lösung ausprobieren:
quelle
Ich habe
RAISERROR
in der Vergangenheit dafür verwendetquelle
Sie können a-
GOTO
undLABEL
Anweisungen einfügen, um Code zu überspringen, sodass dieGO
Schlüsselwörter intakt bleiben.quelle