Muszę przeprowadzić migrację lokalnej bazy danych SQL Server 2017 do bazy danych Azure SQL i mam do czynienia z pewnymi wyzwaniami, ponieważ istnieje wiele ograniczeń.
W szczególności, ponieważ baza danych Azure SQL działa tylko w czasie UTC (bez stref czasowych) i potrzebujemy czasu lokalnego, musimy zmienić użycie GETDATE()
wszędzie w bazie danych, co okazało się więcej pracy, niż się spodziewałem.
Utworzyłem funkcję zdefiniowaną przez użytkownika, aby uzyskać czas lokalny, który działa poprawnie dla mojej strefy czasowej:
CREATE FUNCTION [dbo].[getlocaldate]()
RETURNS datetime
AS
BEGIN
DECLARE @D datetimeoffset;
SET @D = CONVERT(datetimeoffset, SYSDATETIMEOFFSET()) AT TIME ZONE 'Pacific SA Standard Time';
RETURN(CONVERT(datetime,@D));
END
Problem, z którym mam problem, polega na tym, aby zmienić GETDATE()
tę funkcję w każdym widoku, procedurze składowanej, kolumnach obliczeniowych, wartościach domyślnych, innych ograniczeniach itp.
Jaki byłby najlepszy sposób na wdrożenie tej zmiany?
Jesteśmy w publicznej wersji zapoznawczej instancji zarządzanych . Nadal ma ten sam problem GETDATE()
, więc nie pomaga w rozwiązaniu tego problemu. Przeprowadzka na platformę Azure jest wymagana. Ta baza danych jest używana (i będzie używana) zawsze w tej strefie czasowej.
Pracowałbym na odwrót. Konwertuj wszystkie swoje znaczniki czasu w bazie danych na UTC, po prostu użyj UTC i idź z prądem. Jeśli potrzebujesz znacznika czasu w innym tz, możesz utworzyć wygenerowaną kolumnę za pomocą
AT TIME ZONE
(tak jak wcześniej), który renderuje znacznik czasu w określonym TZ (dla aplikacji). Ale poważnie zastanowiłbym się nad powrotem UTC do aplikacji i napisaniem tej logiki - logiki wyświetlania - w aplikacji.źródło
Zamiast eksportować, ręcznie edytować i uruchamiać ponownie, możesz spróbować wykonać zadanie bezpośrednio w bazie danych za pomocą czegoś takiego:
oczywiście rozszerzając go o funkcje, wyzwalacze i tak dalej.
Istnieje kilka zastrzeżeń:
Być może będziesz musiał być nieco jaśniejszy i radzić sobie z inną / dodatkową białą przestrzenią pomiędzy
CREATE
iPROCEDURE
/VIEW
/<other>
. ZamiastREPLACE
tego możesz raczej zostawićCREATE
miejsce na miejscu i wykonaćDROP
pierwsze, ale ryzykuje to pozostawieniemsys.depends
znajomych i zbłąkaniem tam, gdzieALTER
może nie być, a także, jeśli sięALTER
nie powiedzie, masz przynajmniej istniejący obiekt w miejscu, gdzie za pomocąDROP
+CREATE
możesz nie.Jeśli kod ma jakieś „sprytne” zapachy, takie jak modyfikacja własnego schematu za pomocą ad-hoc TSQL, musisz upewnić się, że wyszukiwanie i zamiana na
CREATE
->ALTER
nie przeszkadza w tym.Będziesz chciał przetestować regresję całą aplikację po operacji, niezależnie od tego, czy używasz kursora, czy eksportujesz + edytujesz + uruchamiasz metody.
W przeszłości korzystałem z tej metody, aby dokonywać podobnych aktualizacji dla całego schematu. Jest to trochę hack i wydaje się dość brzydki, ale czasami jest to najłatwiejszy / najszybszy sposób.
Wartości domyślne i inne ograniczenia można również modyfikować podobnie, chociaż można je tylko usunąć i odtworzyć, a nie zmienić. Coś jak:
Więcej zabawy, z którą możesz się zmagać: jeśli partycjonujesz według czasu, te części również mogą wymagać modyfikacji. Podczas gdy partycjonowanie na czas bardziej szczegółowo niż w dzień jest rzadkie, możesz mieć problemy, w których
DATETIME
s są interpretowane przez funkcję partycjonowania jako poprzedni lub następny dzień w zależności od strefy czasowej, pozostawiając partycje bez wyrównania ze zwykłymi zapytaniami.źródło
sys
schemacie i modyfikować programowo.CREATE OR ALTER PROCEDURE
Pomaga rozwiązać niektóre problemy z generowaniem kodu; wciąż mogą występować problemy, ponieważ zapisana definicja zostanie odczytanaCREATE PROCEDURE
(trzy! spacje) i nie jest to zgodne zCREATE PROCEDURE
aniCREATE OR ALTER PROCEDURE
… ._.CREATE
który nie znajduje się w komentarzu, i zastępuje to. Nie miałem tego / podobnego w przeszłości, ale nie mam teraz kodu funkcji przydatnego do opublikowania. Lub jeśli nie możesz zagwarantować, że żadna z twoich definicji obiektów nie zawiera komentarzy poprzedzającychCREATE
, zignoruj problem z komentarzami i po prostu znajdź i zastąp pierwszą instancjęCREATE
.Naprawdę podoba mi się odpowiedź Davida i głosowałem za jej programowym sposobem robienia rzeczy.
Ale możesz wypróbować to dzisiaj, aby uruchomić test na platformie Azure za pośrednictwem SSMS:
Kliknij bazę danych prawym przyciskiem myszy -> Zadania -> Generuj skrypty.
[Back Story] mieliśmy młodszego DBA, który uaktualnił wszystkie nasze środowiska testowe do SQL 2008 R2, podczas gdy nasze środowiska produkcyjne były w SQL 2008. Jest to zmiana, która powoduje, że aż mi się kręci po dziś dzień. Aby przeprowadzić migrację do produkcji, z testów musieliśmy wygenerować skrypty w SQL, używając generowania skryptów, aw zaawansowanych opcjach skorzystaliśmy z opcji „Typ danych do skryptu: schemat i dane”, aby wygenerować ogromny plik tekstowy. Z powodzeniem przenieśliśmy nasze testowe bazy danych R2 na nasze starsze serwery SQL 2008 - gdzie przywracanie bazy danych do niższej wersji nie zadziałałoby. Użyliśmy sqlcmd do wprowadzenia dużego pliku - ponieważ pliki były często zbyt duże dla bufora tekstowego SSMS.
Mówię tutaj, że ta opcja prawdopodobnie również zadziałałaby dla Ciebie. Musisz tylko zrobić jeden dodatkowy krok i wyszukać i zastąpić getdate () przez [dbo] .getlocaldate w wygenerowanym pliku tekstowym. (Chciałbym jednak umieścić twoją funkcję w bazie danych przed migracją).
(Nigdy nie chciałem być biegłym w tym wspomaganiu przywracania bazy danych, ale przez pewien czas stał się defacto sposobem robienia rzeczy. I działało za każdym razem.)
Jeśli wybierzesz tę trasę, upewnij się i wybierz przycisk Zaawansowane i wybierz wszystkie potrzebne opcje (przeczytaj każdą), aby przejść ze starej bazy danych do nowej bazy danych - podobnie jak wspomniane wartości domyślne. Ale daj mu kilka uruchomień testowych na platformie Azure. Założę się, że przekonasz się, że jest to jedno rozwiązanie, które działa - przy odrobinie wysiłku.
źródło
Zauważ, że skomentowano sysobjects Typ warunku kolumny. Mój skrypt zmieni tylko proc i UDF.
Ten skrypt zmieni wszystkie,
Default Constraint
które zawierająGetDate()
źródło
Poparłem odpowiedź Evana Carrolla, ponieważ uważam, że jest to najlepsze rozwiązanie. Nie byłem w stanie przekonać moich kolegów, że powinni zmienić dużo kodu C #, więc musiałem użyć kodu napisanego przez Davida Spilletta. Rozwiązałem kilka problemów z UDF, dynamicznym SQL i schematami (nie wszystkie kody używają „dbo”) w następujący sposób:
i domyślne ograniczenia takie jak to:
UDF
Sugestia użycia UDF, która zwraca dzisiejszą datę i godzinę, wygląda dobrze, ale myślę, że wciąż jest wystarczająco dużo problemów z wydajnością UDF, więc zdecydowałem się na użycie bardzo długiego i brzydkiego rozwiązania AT TIME ZONE.
źródło