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

Hvordan bruger man TimeZoneInfo i en SQLCLR-samling i SQL Server 2012

Opdateret svar

Jeg har skrevet det værktøj, jeg talte om, i det originale svar, som du kan finde her .

Fra og med SQL Server 2016 (og Azure SQL Database) kan du nu bruge AT TIME ZONE nøgleord til at konvertere mellem tidszoner.

Originalt svar

Der er desværre ingen god løsning til at arbejde med tidszoner i SQL Server.

Jeg undersøgte grundigt det problem, du linkede til, sammen med denne også. Der er ingen indbyggede tidszonefunktioner og enhver brug af TimeZoneInfo i SQLCLR kræver assembly at være registreret som "usikker". Dette er normalt ikke ønsket.

Jeg undersøgte også ved hjælp af Noda Time fra SQLCLR. Du kan læse om det i dette nummer . Det skulle også registreres som "usikkert" på grund af den måde, hvorpå visse elementer er cache internt.

I sidste ende, med begge elementer, er problemet, at der ikke er nogen måde at cache noget i SQLCLR. Du kan ikke bruge statiske variabler på en trådsikker måde, og du kan ikke foretage nogen trådsynkronisering eller bruge klasser som ConcurrentDictionary . SQL ønsker at have fuld kontrol over gevindmodellen af ​​samlingen. Kun enkelttrådet brug-en gang-og-smid-væk-stilkode fungerer i "sikre" samlinger. Jeg gravede dybt ned i dette i dette spørgsmål:Multithreaded caching i SQL CLR

Forhåbentlig vil der til sidst være en build af Noda Time, der vil fungere i SQLCLR, men det vil være en speciel build, der ikke laver nogen caching. Så det vil ikke fungere så hurtigt, men det vil få arbejdet gjort, mens det stadig er sikkert.

TimeZoneInfo vil sandsynligvis ikke ændre sig. Så medmindre SQL Server-teamet nogensinde bringer tidszonefunktioner direkte ind i SQL Server korrekt (som Oracle og Postgres gør), så har du kun et par muligheder:

  • Forsøg ikke tidszonekonverteringer i datalaget. Arbejd med datetime eller datetime2 værdier i UTC, eller brug datetimeoffset værdier med enhver offset. Men lav alle konverteringer mellem tidszoner i applikationslaget. Dette er min bedste anbefaling lige nu.

  • Kopier alle data for tidszonerne til faktiske SQL-tabeller, og skriv funktioner, der arbejder med disse data. Dette er ikke den bedste idé, fordi dataene ændres ofte, så tabelvedligeholdelse kan være en udfordring. Det kan også være en udfordring at få funktionerne nøjagtige, inklusive alle reglerne for sommertid. Jeg er ikke bekendt med noget projekt, der har samlet dette pænt og pænt, men hvis nogen er - så lad mig det vide i kommentarerne.

  • Aktiver xp_regread og arbejde med tidszonedataene direkte fra Windows registreringsdatabasenøgler. Opdateringer ville blive lavet for dig, men du har stadig de samme udfordringer med at skrive disse funktioner. Og aktivering af registreringslæsning kan alligevel være lige så stor en sikkerhedsrisiko som at aktivere usikre CLR-samlinger.

En anden idé, jeg overvejer, er at skrive en IANA/Olson TZDB parser og funktioner specifikt til SQL Server. Dette ville ligne mulighed 2 ovenfor, men udført på en måde, der kan vedligeholdes, og med IANA-standarddata i stedet for Windows-tidszoner. Måske når jeg til det her en dag, eller måske vil nogen slå mig til det. Igen, jeg er ikke bekendt med noget aktuelt projekt, der gør dette, men hvis nogen kender til et, så lad mig det vide i kommentarerne. (færdig - se opdatering øverst )

Angående SWITCHOFFSET - det virker kun, når du allerede kender målforskydningen. Det er halvdelen af ​​kampen, og sandsynligvis derfor, Microsoft stadig markerer datetimeoffset som ikke "sommertidsbevidst" i dokumenterne .



  1. SQL-indgange, der udløber efter 24 timer

  2. Tæller tilknyttede poster med Sequelize

  3. Kan en sql-servertabel have to identitetskolonner?

  4. Sådan fungerer Time()-funktionen i SQLite