Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como se usa TimeZoneInfo em um assembly SQLCLR no SQL Server 2012


Resposta atualizada

Eu escrevi o utilitário sobre o qual falei na resposta original, que você pode encontrar aqui .

Além disso, a partir do SQL Server 2016 (e do Banco de Dados SQL do Azure), agora você pode usar o AT TIME ZONE palavra-chave para converter entre fusos horários.

Resposta original

Infelizmente, não existe uma ótima solução para trabalhar com fusos horários no SQL Server.

Investiguei muito o problema que você vinculou, juntamente com este também. Não há funções de fuso horário integradas e qualquer uso de TimeZoneInfo no SQLCLR requer que o assembly seja registrado como "inseguro". Isso geralmente não é desejado.

Também investiguei usando o Noda Time do SQLCLR. Você pode ler sobre isso este problema . Ele também teve que ser registrado como "inseguro" devido à maneira como certos itens são armazenados em cache internamente.

Em última análise, com qualquer item, o problema é que não há como armazenar em cache nada no SQLCLR. Você não pode usar variáveis ​​estáticas de maneira thread-safe e não pode fazer nenhuma sincronização de thread ou usar classes como ConcurrentDictionary . SQL quer ter controle total do modelo de encadeamento do assembly. Somente o código de estilo de uso único e descartável de thread único funciona em assemblies "seguros". Eu me aprofundei nisso nesta pergunta:Cache multithread no SQL CLR

Esperamos que eventualmente ser uma compilação do Noda Time que funcionará no SQLCLR, mas será uma compilação especial que não faz nenhum cache. Portanto, ele não funcionará tão rapidamente, mas fará o trabalho enquanto ainda está seguro.

TimeZoneInfo não é provável que mude. Portanto, a menos que a equipe do SQL Server traga funções de fuso horário diretamente para o SQL Server corretamente (como o Oracle e o Postgres fazem), você terá apenas algumas opções:

  • Não tente fazer conversões de fuso horário na camada de dados. Trabalhar com datetime ou datetime2 valores em UTC ou use datetimeoffset valores com qualquer deslocamento. Mas faça todas as conversões entre fusos horários na camada de aplicação. Esta é a minha melhor recomendação por enquanto.

  • Copie todos os dados dos fusos horários em tabelas SQL reais e escreva funções que funcionem com esses dados. Essa não é a melhor ideia, porque os dados mudam com frequência, então a manutenção da tabela pode ser um desafio. Também obter as funções precisas, incluindo todas as regras de mudança de horário de verão, pode ser um desafio. Eu não estou ciente de nenhum projeto que tenha isso empacotado de maneira agradável e organizada, mas se alguém estiver - então, por favor, deixe-me saber nos comentários.

  • Ativar xp_regread e trabalhe com os dados de fuso horário diretamente das chaves de registro do Windows. Atualizações seriam feitas para você, mas você ainda tem os mesmos desafios ao escrever essas funções. E habilitar leituras de registro pode ser um risco de segurança tão grande quanto habilitar assemblies CLR inseguros de qualquer maneira.

Outra ideia que estou considerando é escrever um IANA/Olson TZDB analisador e funções especificamente para SQL Server. Isso seria semelhante à opção 2 acima, mas feito de maneira sustentável e com dados padrão da IANA em vez de fusos horários do Windows. Talvez eu chegue a isso algum dia, ou talvez alguém me vença. Novamente, não conheço nenhum projeto atual que faça isso, mas se alguém souber de um, por favor, deixe-me saber nos comentários. (concluído - veja atualização no topo )

Sobre SWITCHOFFSET - que só funciona quando você já conhece o deslocamento alvo. Essa é metade da batalha, e provavelmente o motivo pelo qual a Microsoft ainda marca datetimeoffset como não "consciente de horário de verão" nos os documentos .