Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come si usa TimeZoneInfo in un assembly SQLCLR in SQL Server 2012

Risposta aggiornata

Ho scritto l'utilità di cui ho parlato nella risposta originale, che puoi trovare qui .

Inoltre, a partire da SQL Server 2016 (e database SQL di Azure), è ora possibile utilizzare AT TIME ZONE parola chiave per convertire tra i fusi orari.

Risposta originale

Purtroppo non esiste una soluzione ottimale per lavorare con i fusi orari in SQL Server.

Ho studiato a fondo il problema che hai collegato, insieme a questo anche. Non ci sono funzioni di fuso orario integrate e qualsiasi uso di TimeZoneInfo in SQLCLR richiede che l'assembly sia registrato come "non sicuro". Questo di solito non è desiderato.

Ho anche indagato utilizzando Noda Time da SQLCLR. Puoi leggere a riguardo in questo numero . Inoltre doveva essere registrato come "non sicuro" a causa del modo in cui alcuni elementi sono memorizzati internamente nella cache.

In definitiva, con entrambi gli elementi, il problema è che non è possibile memorizzare nella cache nulla in SQLCLR. Non puoi utilizzare variabili statiche in modo thread-safe e non puoi eseguire alcuna sincronizzazione dei thread o utilizzare classi come ConcurrentDictionary . SQL vuole avere il controllo completo del modello di threading dell'assieme. Solo il codice di stile usa e getta a thread singolo funziona negli assembly "sicuri". Ho approfondito questo aspetto in questa domanda:Memorizzazione nella cache multithread in SQL CLR

Si spera che ci sarà alla fine essere una build di Noda Time che funzionerà in SQLCLR, ma sarà una build speciale che non esegue la memorizzazione nella cache. Quindi non funzionerà così rapidamente, ma porterà a termine il lavoro rimanendo al sicuro.

TimeZoneInfo non è probabile che cambi. Quindi, a meno che il team di SQL Server non porti correttamente le funzioni del fuso orario direttamente in SQL Server (come fanno Oracle e Postgres), hai solo poche opzioni:

  • Non tentare conversioni di fuso orario nel livello dati. Lavora con datetime o datetime2 valori in UTC oppure usa datetimeoffset valori con qualsiasi offset. Ma esegui tutte le conversioni tra i fusi orari nel livello dell'applicazione. Questa è la mia migliore raccomandazione per ora.

  • Copia tutti i dati per i fusi orari nelle tabelle SQL effettive e scrivi funzioni che funzionano con quei dati. Questa non è l'idea migliore, perché i dati cambiano spesso, quindi la manutenzione delle tabelle può essere una sfida. Anche ottenere le funzioni accurate, comprese tutte le regole di modifica dell'ora legale, può essere difficile. Non sono a conoscenza di alcun progetto che abbia questo insieme carino e ordinato, ma se qualcuno lo è, per favore fatemelo sapere nei commenti.

  • Abilita xp_regread e lavorare con i dati del fuso orario direttamente dalle chiavi di registro di Windows. Gli aggiornamenti verrebbero fatti per te, ma hai ancora le stesse difficoltà nello scrivere queste funzioni. Inoltre, l'abilitazione delle letture del registro potrebbe rappresentare un rischio per la sicurezza tanto quanto l'abilitazione di assembly CLR non sicuri.

Un'altra idea che sto considerando è quella di scrivere un IANA/Olson TZDB parser e funzioni specifiche per SQL Server. Sarebbe simile all'opzione 2 sopra, ma eseguita in modo gestibile e con dati standard IANA anziché fusi orari di Windows. Forse ci arriverò un giorno, o forse qualcuno mi batterà. Ancora una volta, non sono a conoscenza di alcun progetto attuale che lo faccia, ma se qualcuno ne conosce uno, per favore fatemelo sapere nei commenti. (fatto - vedi aggiornamento in alto )

Riguardo a SWITCHOFFSET - funziona solo quando conosci già l'offset target. Questa è metà della battaglia e probabilmente il motivo per cui Microsoft contrassegna ancora datetimeoffset come non "consapevole dell'ora legale" in i documenti .