T-SQL "re-runnable" skrypty aktualizacji bazy danych - usunięcie kolumna

głosy
1

Do naszej bazy danych SQL Server, używamy system wersjonowania śledzić aktualizacje schematu. Chodzi o to, że powinieneś być w stanie uruchomić ten skrypt, aby przynieść schematu z poprzedniej wersji do bieżącej wersji. ponownie uruchamiając skrypt główny powinien wykonać tylko najnowsze aktualizacje schematu.

Struktura skryptu jest tak:

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=0
 IF (@Installed IS NULL)
 BEGIN
    ...
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 0, GetDate())
 END
 ELSE PRINT 'Version 1.0.0 was already installed on ' + Convert(varchar(10), @Installed)  

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=1
 IF (@Installed IS NULL)
 BEGIN
    ...
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 1, GetDate())
 END
 ELSE PRINT 'Version 1.0.1 was already installed on ' + Convert(varchar(10), @Installed)

To zazwyczaj działa bardzo dobrze. Jednak mamy napotkał problem, gdy aktualizacja schematu kropli kolumnę, który jest dołączony w poprzednim INSERT ignorować; Oznacza to, że mają coś takiego:

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=0
 IF (@Installed IS NULL)
 BEGIN
    INSERT IGNORE  [foo] ([a], [b], [OrganizationId]) VALUES (N'a', N'b', N'1');
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 0, GetDate());
 END
 ELSE PRINT 'Version 1.0.0 was already installed on ' + Convert(varchar(10), @Installed)  

 SELECT @Installed = InstallDate FROM SystemSchemaVersion WHERE Major=1 AND Minor=0 AND Patch=1
 IF (@Installed IS NULL)
 BEGIN
    ALTER TABLE [foo] DROP COLUMN [OrganizationId];
    INSERT IGNORE  INTO SystemSchemaVersion (Major, Minor, Patch, InstallDate) VALUES (1, 0, 1, GetDate());
 END
 ELSE PRINT 'Version 1.0.1 was already installed on ' + Convert(varchar(10), @Installed)

Działa to dobrze za pierwszym razem jest on wykonywany; Wersja 1.0.1 jest wykonywane, a kolumna jest odrzucany. Jednak uruchomienie skryptu do drugiego plony czas:

    Msg 207, Level 16, State 1, Linia 7118
    Nieprawidłowa nazwa kolumny „OrganizationId”.

Oznacza to, że nawet jeśli INSERT IGNORE wewnątrz bloku wersja 1.0.0 nie jest wykonywany, to wciąż jest analizowany i generowania nieprawidłowy błąd kolumny.

Wszelkie sugestie dotyczące sposobu obejścia tego? Idealnie chciałabym chronić INSERT IGNORE z warunkowego tak, że nie jest nawet analizowany, ale to nie wydaje się dzieje. Mógłbym dynamicznie wykonać INSERT IGNORE s wewnątrz sp_executesql () wywołuje, ale wolałbym nie (wymagałoby dużo doposażenia).

Dzięki --

--Andy

Utwórz 27/08/2009 o 01:51
źródło użytkownik
W innych językach...                            


4 odpowiedzi

głosy
1

Ok, ja mis-przeczytać początkowo pytanie. :-)

W przypadku zmiany linii Wstaw z:

INSERT IGNORE  [foo] ([a], [b], [OrganizationId]) VALUES (N'a', N'b', N'1');

do:

exec('INSERT IGNORE  [foo] ([a], [b], [OrganizationId]) VALUES (''a'', ''b'', ''1'')');

Nie powinien mieć ten problem, ponieważ SQL „text” wewnątrz Exec nie będą przetwarzane do exec () jest faktycznie nazwie.

Odpowiedział 27/08/2009 o 02:40
źródło użytkownik

głosy
1

Niestety ten jest podobny do problemu można dostać kiedy (wewnątrz przechowywanych proc) upuszczeniu tabeli tymczasowej, a następnie odtworzyć go. Parser będzie narzekać, że już istnieje, nie zdając sobie sprawę, że tabela tymczasowa właśnie został upuszczony.

Jeśli oddzielić go ze sprawozdania odejść, wtedy należy znaleźć system ponownie oceni każdą sekcję jak przychodzi do niego.

Obrabować

Odpowiedział 27/08/2009 o 02:08
źródło użytkownik

głosy
0

Czy próbowałeś Dynamiczny SQL? Niestety, parser będzie sprawdzał cały skrypt przed uruchomieniem go, więc każda kolumna będzie nieważny zatrzymać egzekucję.

Odpowiedział 27/08/2009 o 02:22
źródło użytkownik

głosy
0

Używamy prawie identyczną konfigurację do czynienia z wersjami schematu.

W ogóle, twoje podejście jest całkowicie zdrowe. Byliśmy uruchomiony z tej ogólnej konfiguracji kilku lat. Zasadniczo, aby obsługiwać żadnych destrukcyjnych lub niekompatybilny zmian schematu, możemy uruchomić łatki jako część zautomatyzowanego build CruiseControl.NET.

Więc nasza budowa bazy danych wygląda następująco ...

  • Przywracanie z kopii zapasowej bieżącej wersji produkcyjnej.
  • Sprawdzić wersję odrestaurowanym DB
  • Uruchom wszystkie poprawki (te są nazywane przez konferencyjnego przy użyciu major.minor.sql), które są później niż w wersji podanej w tabeli [Wersje].

W ten sposób możemy przebudować cały dzień bez żadnych problemów, bez względu na to, co robi łata. Gwarantuje również, że kiedy mamy wdrożyć produkcji nie występują żadne problemy, ponieważ mamy już wdrożony przez 1000x db produkcji w trakcie rozwoju.

Odpowiedział 27/08/2009 o 02:12
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more