Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment utiliser TimeZoneInfo dans un assembly SQLCLR dans SQL Server 2012

Réponse mise à jour

J'ai écrit l'utilitaire dont j'ai parlé dans la réponse d'origine, que vous pouvez trouver ici .

De plus, à partir de SQL Server 2016 (et Azure SQL Database), vous pouvez désormais utiliser le AT TIME ZONE mot-clé à convertir entre les fuseaux horaires.

Réponse originale

Malheureusement, il n'existe pas de solution idéale pour travailler avec les fuseaux horaires dans SQL Server.

J'ai étudié de manière approfondie le problème que vous avez lié, ainsi que celui-ci aussi. Il n'y a pas de fonctions de fuseau horaire intégrées et toute utilisation de TimeZoneInfo dans SQLCLR nécessite que l'assembly soit enregistré comme "non sécurisé". Ce n'est généralement pas souhaité.

J'ai également étudié l'utilisation de Noda Time de SQLCLR. Vous pouvez lire à ce sujet dans ce numéro . Il devait également être enregistré comme "non sécurisé" en raison de la façon dont certains éléments sont mis en cache en interne.

En fin de compte, avec l'un ou l'autre élément, le problème est qu'il n'y a aucun moyen de mettre en cache quoi que ce soit dans SQLCLR. Vous ne pouvez pas utiliser de variables statiques de manière sécurisée pour les threads, et vous ne pouvez pas synchroniser les threads ou utiliser des classes comme ConcurrentDictionary . SQL veut avoir le contrôle total du modèle de threading de l'assembly. Seul le code de style à usage unique et jetable à un seul thread fonctionne dans les assemblages "sûrs". J'ai creusé profondément dans cette question :Mise en cache multithread dans SQL CLR

Espérons qu'il y aura éventuellement être une version de Noda Time qui fonctionnera dans SQLCLR, mais ce sera une version spéciale qui ne fera aucune mise en cache. Il ne fonctionnera donc pas aussi rapidement, mais il fera le travail tout en étant sûr.

TimeZoneInfo ne risque pas de changer. Donc, à moins que l'équipe SQL Server n'intègre correctement les fonctions de fuseau horaire directement dans SQL Server (comme le font Oracle et Postgres), vous n'avez que quelques options :

  • N'essayez pas de convertir les fuseaux horaires dans la couche de données. Travailler avec datetime ou datetime2 valeurs en UTC, ou utilisez datetimeoffset valeurs avec n'importe quel décalage. Mais faites toutes les conversions entre les fuseaux horaires dans la couche d'application. C'est ma meilleure recommandation pour le moment.

  • Copiez toutes les données des fuseaux horaires dans des tables SQL réelles et écrivez des fonctions qui fonctionnent avec ces données. Ce n'est pas la meilleure idée, car les données changent souvent, de sorte que la maintenance des tables peut être un défi. Il peut également être difficile d'obtenir des fonctions précises, y compris toutes les règles de changement d'heure d'été. Je ne suis au courant d'aucun projet qui intègre cela de manière agréable et soignée, mais si quelqu'un l'est, veuillez me le faire savoir dans les commentaires.

  • Activer xp_regread et travaillez avec les données de fuseau horaire directement à partir des clés de registre Windows. Des mises à jour seraient faites pour vous, mais vous avez toujours les mêmes difficultés à écrire ces fonctions. De plus, l'activation des lectures de registre peut présenter autant de risques pour la sécurité que l'activation d'assemblys CLR non sécurisés.

Une autre idée que j'envisage est d'écrire un IANA/Olson TZDB analyseur et fonctions spécifiquement pour SQL Server. Cela serait similaire à l'option 2 ci-dessus, mais fait de manière maintenable et avec les données standard de l'IANA au lieu des fuseaux horaires Windows. Peut-être que j'y arriverai un jour, ou peut-être que quelqu'un me devancera. Encore une fois, je ne suis au courant d'aucun projet en cours qui le fasse, mais si quelqu'un en connaît un, merci de me le faire savoir dans les commentaires. (fait - voir la mise à jour en haut )

Concernant SWITCHOFFSET - cela ne fonctionne que lorsque vous connaissez déjà le décalage cible. C'est la moitié de la bataille, et probablement pourquoi Microsoft marque toujours datetimeoffset comme non "conscient de l'heure d'été" dans la documentation .