Generuję skrypt do automatycznej migracji zmian z wielu programistycznych baz danych do przemieszczania / produkcji. Zasadniczo wymaga kilku skryptów zmian i łączy je w jeden skrypt, opakowując każdy skrypt w IF whatever BEGIN ... END
instrukcję.
Jednak niektóre skrypty wymagają GO
instrukcji, aby na przykład parser SQL wiedział o nowej kolumnie po jej utworzeniu.
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
Jednak kiedy zawinąłem to w IF
blok:
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
Nie udaje się, ponieważ wysyłam BEGIN
bez dopasowania END
. Jeśli jednak usunę GO
to znowu narzeka na nieznaną kolumnę.
Czy istnieje sposób na utworzenie i zaktualizowanie tej samej kolumny w jednym IF
bloku?
sql
sql-server
tsql
sql-server-2008
BlueRaja - Danny Pflughoeft
źródło
źródło
GO
musi znajdować się w osobnej linii, więc możesz wyszukać tylko ten przypadek, a nie każde wystąpienie tego słowaGO
. 2) Zawsze możesz zarejestrować, które instrukcje zostały pomyślnie wykonane. Lub możesz zawinąć całość w try / catch i użyć własnych numerów linii, używając jakiejś zmiennej, takiej jak @lineNo, którą śledzisz i zgłaszać błąd. Ponieważ generujesz je automatycznie, wprowadzanie takich zmian powinno być proste. Wygląda na to, że po prostu nie chcesz badać tej drogi, kiedy myślę, że są rozwiązania, które można znaleźć dla wszystkich twoich obaw.Odpowiedzi:
Miałem ten sam problem iw końcu udało mi się go rozwiązać za pomocą SET NOEXEC .
źródło
SQLCMD
skrypcie trybu SS (tj. Głównym skrypcie wdrażania), który wywołuje (za pośrednictwem:r
polecenia) inne skrypty SS (tj. Skrypty wdrażania podrzędnego) z niektórymi z tych wywołań wewnątrzif
instrukcji. Odpowiedzi Odeda, mellamokb i Andy'ego Joinera dotyczące załączania wszystkich tych stwierdzeń doexec
wezwań /begin
-end
nie są początkowe. Ponadto metodabegin
-end
nie zadziała, jeśli istniejecreate
instrukcja (np. Wymagago
przed nią jawnego ). Ale człowieku, "Święte podwójne negatywy, Batmanie!" ;)if
blok), poprzedziłbym blok-- If whatever
komentarzem, wciąłbym blok i dodał do niego--end If whatever
komentarz.GO
to nie jest SQL - to po prostu separator wsadowy używany w niektórych narzędziach MS SQL.Jeśli tego nie używasz, musisz upewnić się, że instrukcje są wykonywane osobno - w różnych partiach lub przy użyciu dynamicznego SQL dla populacji (dzięki @gbn):
źródło
IF
bloku.;
pomoc byłaby tutaj? - Właśnie zredagowałeś swoją odpowiedź: o);
też nie działa - parser nadal podaje mi komunikat „Nieprawidłowa nazwa kolumny 'EMP_IS_ADMIN'."Możesz spróbować podzielić
sp_executesql
zawartość między każdąGO
instrukcją na oddzielny ciąg do wykonania, jak pokazano w poniższym przykładzie. Istnieje również zmienna @statementNo do śledzenia, która instrukcja jest wykonywana, aby ułatwić debugowanie, w którym wystąpił wyjątek. Numery wierszy będą podane względem początku odpowiedniego numeru instrukcji, który spowodował błąd.Możesz również łatwo wykonywać instrukcje wielowierszowe, jak pokazano w powyższym przykładzie, po prostu zawijając je w pojedyncze cudzysłowy (
'
).''
Podczas generowania skryptów nie zapomnij o zastąpieniu pojedynczych cudzysłowów zawartych w ciągu znaków za pomocą podwójnego apostrofu ( ).źródło
SELECT * <newline> FROM whatever
. Jeśli wykonam każdy wiersz z własną instrukcją EXEC, to się zepsuje. A może sugerujesz, żebym łamał się przy każdymGO
stwierdzeniu?Ostatecznie udało mi się go uruchomić, zastępując każdą instancję
GO
na własnej linii przezJest to znacznie lepsze niż zawijanie każdej grupy instrukcji w łańcuch, ale nadal jest dalekie od ideału. Jeśli ktoś znajdzie lepsze rozwiązanie, opublikuj je, a ja je zaakceptuję.
źródło
IF
bloku). Wydaje się, że po prostu nie ma dobrego sposobu na zrobienie tego w SQL.set noexec
Odpowiedź Miny Jacob jest jak dotąd JEDYNĄ praktyczną odpowiedzią do użycia wSQLCMD
skrypcie trybu SS (tj. Głównym skrypcie wdrażania), który wywołuje (za pomocą:r
polecenia) inne skrypty SS (tj. Skrypty wdrażania podrzędnego) z niektórymi z tych wywołań wewnątrzif
instrukcji. Odpowiedzi Odeda, mellamokb i Andy'ego Joinera dotyczące załączania wszystkich tych stwierdzeń doexec
wezwań /begin
-end
nie są początkowe. Ponadto metodabegin
-end
nie zadziała, jeśli istniejecreate
instrukcja (np. Wymagago
przed nią jawnego ).Możesz ująć instrukcje w BEGIN i END zamiast GO pomiędzy
(Testowane w bazie danych Northwind)
Edycja: (prawdopodobnie przetestowane na SQL2012)
źródło
set noexec
Odpowiedź Miny Jacob jest jak dotąd JEDYNĄ praktyczną odpowiedzią do użycia wSQLCMD
skrypcie trybu SS (tj. Głównym skrypcie wdrażania), który wywołuje (za pomocą:r
polecenia) inne skrypty SS (tj. Skrypty wdrażania podrzędnego) z niektórymi z tych wywołań wewnątrzif
instrukcji. Odpowiedzi Odeda, mellamokb i Andy Joinera dotyczące załączania wszystkich tych stwierdzeń wexec
wezwaniach /begin
-end
nie są początkowe. Ponadto metodabegin
-end
nie zadziała, jeśli istniejecreate
instrukcja (np. Wymagago
przed nią jawnego ).Możesz wypróbować to rozwiązanie:
źródło
Używałem tego
RAISERROR
w przeszłościźródło
Możesz dołączyć instrukcje a
GOTO
iLABEL
, aby pominąć kod, pozostawiając w ten sposóbGO
słowa kluczowe nietknięte.źródło