sql >> Databáze >  >> RDS >> Sqlserver

Jak se používá TimeZoneInfo v sestavení SQLCLR v SQL Server 2012

Aktualizovaná odpověď

Napsal jsem nástroj, o kterém jsem mluvil v původní odpovědi, který najdete zde .

Od SQL Server 2016 (a Azure SQL Database) můžete nyní také používat AT TIME ZONE klíčové slovo pro převod mezi časovými pásmy.

Původní odpověď

Bohužel neexistuje žádné skvělé řešení pro práci s časovými pásmy na serveru SQL Server.

Důkladně jsem prošetřil problém, na který jste odkazoval, spolu s tímto taky. Neexistují žádné vestavěné funkce časového pásma a jakékoli použití TimeZoneInfo v SQLCLR vyžaduje, aby sestavení bylo registrováno jako "nebezpečné". To obvykle není žádoucí.

Zkoumal jsem také pomocí Noda Time z SQLCLR. Můžete si o tom přečíst toto vydání . Také musel být registrován jako „nebezpečný“ kvůli způsobu, jakým jsou určité položky interně ukládány do mezipaměti.

Nakonec u obou položek je problém v tom, že v SQLCLR nelze nic uložit do mezipaměti. Nemůžete používat statické proměnné způsobem bezpečným pro vlákna a nemůžete provádět žádnou synchronizaci vláken ani používat třídy jako ConcurrentDictionary . SQL chce mít plnou kontrolu nad modelem vláken sestavy. V "bezpečných" sestavách funguje pouze jednovláknový kód stylu použití jednou a zahoď. V této otázce jsem se hlouběji zabýval:Ukládání do mezipaměti s více vlákny v SQL CLR

Doufejme, že nakonec dojde být sestavení Noda Time, které bude fungovat v SQLCLR, ale bude to speciální sestavení, které neprovádí žádné ukládání do mezipaměti. Nebude tedy fungovat tak rychle, ale svou práci zvládne a přitom bude stále v bezpečí.

TimeZoneInfo se pravděpodobně nezmění. Takže pokud tým SQL Serveru nikdy nezavede funkce časových pásem přímo do SQL Serveru správně (jako Oracle a Postgres), pak máte jen několik možností:

  • Nepokoušejte se převádět časové pásmo v datové vrstvě. Pracujte s datetime nebo datetime2 hodnoty v UTC nebo použijte datetimeoffset hodnoty s libovolným posunem. Všechny převody mezi časovými pásmy však provádějte v aplikační vrstvě. Toto je moje nejlepší doporučení.

  • Zkopírujte všechna data pro časová pásma do skutečných tabulek SQL a zapište funkce, které s těmito daty pracují. To není nejlepší nápad, protože data se často mění, takže údržba tabulky může být problém. Také získání přesných funkcí, včetně všech pravidel změny letního času, může být náročné. Nevím o žádném projektu, který by to měl pěkně a úhledně zabalené, ale pokud někdo ano, dejte mi prosím vědět v komentářích.

  • Povolit xp_regread a pracovat s daty časového pásma přímo z klíčů registru systému Windows. Aktualizace by byly provedeny za vás, ale stále máte stejné problémy při psaní těchto funkcí. A povolení čtení registru může být stejně tak bezpečnostní riziko jako povolení nebezpečných sestavení CLR.

Dalším nápadem, který zvažuji, je napsat IANA/Olson TZDB parser a funkce speciálně pro SQL Server. To by bylo podobné možnosti 2 výše, ale provedeno udržitelným způsobem a se standardními daty IANA namísto časových pásem Windows. Možná se k tomu někdy dostanu, nebo mě k tomu možná někdo předběhne. Opět si nejsem vědom žádného současného projektu, který by to dělal, ale pokud někdo o nějakém ví, dejte mi prosím vědět v komentářích. (hotovo – viz aktualizace nahoře )

Ohledně SWITCHOFFSET - to funguje pouze tehdy, když již znáte cílový offset. To je polovina úspěchu a pravděpodobně proto Microsoft stále označuje datetimeoffset v dokumentech .



  1. Jak FIND_IN_SET() funguje v MariaDB

  2. Klíčové slovo FROM nebylo nalezeno, kde se očekávalo, výběr textu Oracle SQL

  3. Aktualizace div při kliknutí na tlačítko, když je tlačítko vygenerováno kliknutím na jiné tlačítko

  4. co se odstraní z tabulky, kde znamená NULL =NULL?