Preciso migrar um banco de dados local do SQL Server 2017 para um banco de dados SQL do Azure e estou enfrentando alguns desafios, pois há algumas limitações a serem enfrentadas.
Em particular, como um banco de dados SQL do Azure funciona apenas no horário UTC (sem fuso horário) e precisamos do horário local, precisamos alterar o uso de GETDATE()
qualquer lugar no banco de dados, o que provou ser mais trabalhoso do que eu esperava.
Criei uma função definida pelo usuário para obter a hora local que funciona corretamente para o meu fuso horário:
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
O problema com o qual estou tendo problemas é realmente mudar GETDATE()
com essa função em todas as visualizações, procedimentos armazenados, colunas computadas, valores padrão, outras restrições etc.
Qual seria a melhor maneira de implementar essa mudança?
Estamos na pré-visualização pública de Instâncias gerenciadas . Ele ainda tem o mesmo problema e GETDATE()
, portanto, não ajuda com esse problema. Mover para o Azure é um requisito. Esse banco de dados é usado (e será usado) sempre neste fuso horário.
Eu trabalharia o contrário. Converta todos os seus carimbos de data e hora no banco de dados para UTC e use apenas o UTC e siga o fluxo. Se você precisar de um carimbo de data e hora em um tz diferente, poderá criar uma coluna gerada usando
AT TIME ZONE
(como você fez acima) que renderiza o carimbo de data e hora na TZ especificada (para o aplicativo). Mas, seriamente, consideraria apenas ter o UTC retornado ao aplicativo e escrever essa lógica - a lógica de exibição - no aplicativo.fonte
Em vez de exportar, editar manualmente e executar novamente, você pode tentar fazer o trabalho diretamente no banco de dados com algo como:
é claro estendendo-o para lidar com funções, gatilhos e assim por diante também.
Existem algumas ressalvas:
Você pode precisar ser um pouco mais inteligente e lidar com espaços em branco diferentes / extras entre
CREATE
ePROCEDURE
/VIEW
/<other>
. Ao invés doREPLACE
para que você pode preferir deixar em vez disso oCREATE
no lugar e executar umDROP
primeiro, mas esta riscos deixandosys.depends
e amigos fora dos eixos, ondeALTER
não podem, também, seALTER
falhar, você pelo menos tem o objeto existente ainda no lugar onde, comDROP
+CREATE
você pode não.Se você codificar algum cheiro "inteligente", como modificar seu próprio esquema com TSQL ad-hoc, será necessário garantir que a pesquisa e a substituição de
CREATE
->ALTER
não interfiram nisso.Você desejará testar a regressão do (s) aplicativo (s) inteiro (s) após a operação, independentemente de usar o cursor ou exportar + editar + executar métodos.
Eu usei esse método para fazer atualizações semelhantes em todo o esquema no passado. É um pouco complicado, e parece muito feio, mas às vezes é a maneira mais fácil / rápida.
Padrões e outras restrições também podem ser modificados da mesma forma, embora apenas possam ser eliminados e recriados em vez de alterados. Algo como:
Um pouco mais divertido com o qual você pode precisar lidar: se você estiver particionando com o tempo, essas partes também precisarão ser alteradas. Embora o particionamento no horário mais granularmente do que o dia seja raro, você pode ter problemas em que
DATETIME
s são interpretados pela função de particionamento como sendo o dia anterior ou o próximo, dependendo do fuso horário, deixando suas partições desalinhadas com as consultas habituais.fonte
sys
esquema e modificados programaticamente.CREATE OR ALTER PROCEDURE
ajude a solucionar alguns problemas de geração de código; ainda pode haver problemas, pois a definição armazenada será lidaCREATE PROCEDURE
(três! espaços) e isso não é correspondido porCREATE PROCEDURE
nemCREATE OR ALTER PROCEDURE
… ._.CREATE
que não está em um comentário e a substitui. Eu não tenho isso / semelhante no passado, mas não tenho o código da função à mão agora para postar. Ou se você pode garantir que nenhuma das suas definições de objeto possua comentários anterioresCREATE
, ignore o problema dos comentários e localize e substitua a primeira instância deCREATE
.Eu realmente gosto da resposta de David e votei nisso por uma maneira programática de fazer as coisas.
Mas você pode tentar isso hoje para uma execução de teste no Azure via SSMS:
Clique com o botão direito do mouse em seu banco de dados -> Tarefas -> Gerar scripts.
[História anterior], tivemos um DBA júnior que atualizou todos os nossos ambientes de teste para o SQL 2008 R2 enquanto nossos ambientes de produção estavam no SQL 2008. É uma mudança que me faz estremecer até hoje. Para migrar para a produção, a partir do teste, tivemos que gerar scripts dentro do SQL, usando gerar scripts, e nas opções avançadas usamos a opção 'Tipo de dados para script: esquema e dados' para gerar um arquivo de texto massivo. Conseguimos mover com êxito nossos bancos de dados R2 de teste para nossos servidores herdados do SQL 2008 - onde uma restauração de banco de dados para uma versão inferior não teria funcionado. Usamos o sqlcmd para inserir o arquivo grande - pois os arquivos geralmente eram grandes demais para o buffer de texto do SSMS.
O que estou dizendo aqui é que essa opção provavelmente funcionaria para você também. Você só precisará executar uma etapa adicional e pesquisar e substituir getdate () por [dbo] .getlocaldate no arquivo de texto gerado. (Eu colocaria sua função no banco de dados antes da migração).
(Eu nunca quis ser proficiente nesse curativo de restauração de banco de dados, mas por um tempo tornou-se uma maneira defacto de fazer as coisas. E funcionou sempre.)
Se você escolher esta rota, certifique-se de selecionar o botão Avançado e todas as opções necessárias (leia cada uma) para passar do banco de dados antigo para o novo - como os padrões mencionados. Mas faça alguns testes no Azure. Aposto que você descobrirá que essa é uma solução que funciona - com um mínimo de esforço.
fonte
Observe que os sysobjects comentados digitam a condição da coluna. Meu script alterará apenas proc e UDF.
Este script irá alterar tudo o
Default Constraint
que contémGetDate()
fonte
Promovi a resposta de Evan Carrolls, pois acho que essa é a melhor solução. Não consegui convencer meus colegas de que eles deveriam alterar muito código C #; portanto, tive que usar o código que David Spillett escreveu. Corrigi alguns problemas com UDFs, SQL dinâmico e esquemas (nem todos os códigos usam "dbo.") Como este:
e as restrições padrão como esta:
UDFs
A sugestão de usar um UDF que retorne a data e a hora de hoje parece bom, mas acho que ainda existem problemas de desempenho suficientes com os UDFs, por isso escolhi usar a solução AT TIME ZONE muito longa e feia.
fonte