Мне нужно перенести локальную базу данных SQL Server 2017 в базу данных SQL Azure, и я сталкиваюсь с некоторыми проблемами, так как есть довольно много ограничений, которые необходимо пройти.
В частности, поскольку база данных SQL Azure работает только во времени UTC (без часовых поясов) и нам нужно местное время, нам нужно изменить использование GETDATE()
повсюду в базе данных, что оказалось более трудоемким, чем я ожидал.
Я создал пользовательскую функцию, чтобы получить местное время, которое работает правильно для моего часового пояса:
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
Проблема, с которой я сталкиваюсь, заключается в том, чтобы фактически изменять GETDATE()
эту функцию в каждом представлении, хранимой процедуре, вычисляемых столбцах, значениях по умолчанию, других ограничениях и т. Д.
Как лучше всего осуществить это изменение?
Мы находимся в публичном обзоре управляемых экземпляров . Он все еще имеет ту же проблему GETDATE()
, поэтому он не помогает с этой проблемой. Переход на Azure является обязательным требованием. Эта база данных используется (и будет использоваться) всегда в этом часовом поясе.
Я бы работал наоборот. Преобразуйте все свои временные метки в базе данных в UTC, и просто используйте UTC и продолжайте. Если вам нужна временная метка в другом tz, вы можете создать сгенерированный столбец, используя
AT TIME ZONE
(как вы делали выше) визуализацию временной метки в указанном TZ (для приложения). Но я бы серьезно подумал о том, чтобы просто вернуть UTC в приложение и написать эту логику - логику отображения - в приложении.источник
Вместо экспорта, ручного редактирования и повторного запуска вы можете попробовать выполнить работу непосредственно в базе данных с помощью чего-то вроде:
конечно, расширяя его, чтобы иметь дело с функциями, триггерами и так далее.
Есть несколько предостережений:
Возможно, вам нужно быть немного ярче и иметь дело с разным / дополнительным пробелом между
CREATE
иPROCEDURE
/VIEW
/<other>
. Вместо того,REPLACE
для чего вы могли бы предпочесть вместо этого оставить наCREATE
месте и выполнитьDROP
первое, но это может привести к тому, что вы покидаетеsys.depends
и друзей вне зависимости от того, чтоALTER
может и не произойти, также, в случаеALTER
неудачи, вы по крайней мере сохраняете существующий объект на месте, где с помощьюDROP
+CREATE
вы можете не.Если в вашем коде есть какие-то "умные" запахи, такие как изменение собственной схемы с помощью специального TSQL, то вам нужно убедиться, что поиск и замена
CREATE
->ALTER
не мешают этому.Вы захотите провести регрессионное тестирование всего приложения после операции, используете ли вы курсор или методы export + edit + run.
Я использовал этот метод для создания аналогичных обновлений для всей схемы в прошлом. Это что-то вроде хака и кажется довольно уродливым, но иногда это самый простой / быстрый способ.
Значения по умолчанию и другие ограничения также могут быть изменены аналогичным образом, хотя они могут быть только удалены и воссозданы, а не изменены. Что-то типа:
Еще немного удовольствия, с которым вам, возможно, придется бороться: если вы разбиваете по времени, эти части тоже могут нуждаться в изменении. Хотя разбиение по времени более детально, чем по дням, встречается редко, у вас могут возникнуть проблемы, когда
DATETIME
функция интерпретации интерпретируется как предыдущий или следующий день в зависимости от времени, оставляя ваши разделы не выровненными с вашими обычными запросами.источник
sys
схеме и программно изменить.CREATE OR ALTER PROCEDURE
помогает решить некоторые проблемы генерации кода; Тем не менее могут возникнуть проблемы, поскольку сохраненное определение будет читатьCREATE PROCEDURE
(три! пробела), и это не соответствуетCREATE PROCEDURE
ниCREATE OR ALTER PROCEDURE
… ._.CREATE
, но не внутри комментария, и заменяет ее. В прошлом я этого не делал, но сейчас у меня нет удобного кода функции для публикации. Или, если вы можете гарантировать, что ни в одном из ваших определений объектов не будет комментариев, предшествующихCREATE
, игнорируйте проблему с комментариями и просто найдите и замените первый экземплярCREATE
.Мне очень нравится ответ Дэвида, и я проголосовал за его программный подход.
Но вы можете попробовать это сегодня для пробного запуска в Azure через SSMS:
Щелкните правой кнопкой мыши по вашей базе данных -> Задачи -> Создать сценарии.
[Back Story] У нас был младший администратор базы данных, который обновил все наши тестовые среды до SQL 2008 R2, в то время как наши производственные среды были на SQL 2008. Это изменение, которое заставляет меня сковывать по сей день. Чтобы перейти к производству, из теста нам нужно было генерировать скрипты в SQL с использованием скриптов генерирования, а в расширенных настройках мы использовали опцию «Тип данных для скрипта: схема и данные» для генерации массивного текстового файла. Мы успешно смогли перенести наши тестовые базы данных R2 на наши устаревшие серверы SQL 2008 - там, где восстановление базы данных на более низкую версию не работало бы. Мы использовали sqlcmd для ввода большого файла - поскольку файлы часто были слишком большими для текстового буфера SSMS.
Я хочу сказать, что этот вариант, вероятно, будет работать и для вас. Вам просто нужно сделать один дополнительный шаг и выполнить поиск и заменить getdate () на [dbo] .getlocaldate в сгенерированном текстовом файле. (Я бы положил вашу функцию в базу данных до миграции, хотя).
(Я никогда не хотел быть опытным в этой помощи при восстановлении базы данных, но какое-то время это стало неэффективным способом выполнения действий. И это работало каждый раз.)
Если вы выберете этот маршрут, убедитесь, что нажмите кнопку «Дополнительно» и выберите все необходимые параметры (прочитайте каждый), чтобы перейти от старой базы данных к новой, например, по умолчанию. Но проведите несколько тестовых прогонов в Azure. Могу поспорить, вы обнаружите, что это одно решение, которое работает - с небольшим усилием.
источник
Комментарий прокомментирован sysobjects Тип столбца условие. Мой скрипт будет изменять только proc и UDF.
Этот скрипт будет изменять все,
Default Constraint
что содержитGetDate()
источник
Я проголосовал за ответ Эвана Кэрролла, так как считаю, что это лучшее решение. Я не смог убедить моих коллег в том, что они должны сильно изменить код C #, поэтому мне пришлось использовать код, который написал Дэвид Спиллетт. Я исправил несколько проблем с UDF, динамическим SQL и схемами (не весь код использует «dbo»), например так:
и ограничения по умолчанию, как это:
UDFs
Предложение использовать UDF, которое возвращает сегодняшнюю дату и время, выглядит неплохо, но я думаю, что с UDF все еще достаточно проблем с производительностью, поэтому я решил использовать очень длинное и уродливое решение AT TIME ZONE.
источник