SQL Server

SET DATEFORMAT

Stává se poměrně často, že potřebujeme převést datum uložený jako textový řetězec na některý z datových typů určených přímo pro ukládání data a času (např. datetime, datetime2, date, etc.). Jak ale zajistíme, aby SQL Server správně rozuměl textovému řetězci a poznal zejména to, v jakém pořadí jsou v něm uloženy měsíce a dny, protože do 12. dnes v měsíci nám vše bude fungovat skvěle (např. datum 12.12.2019), neboť nezáleží na tom, na jaké pozici jsou dny a kde měsíce. Jakmile ale počet dnů bude 13 a výše, může se lehce stát, že naše konverze z řetězce na datumový typ selže, protože si SQL Server bude myslet, že převádí z dané pozici číselnou hodnotu na měsíce, ale ouha, ony jsou na této pozici uloženy dny a cokoliv větší než 12 na měsíce převést nelze. Jak se můžeme této nečekané situaci vyhnout si ukážeme pomocí SET DATEFORMAT, kterým pro dané připojení určíme, jak má SQL Server interpretovat textový řetězec při převodu na některý z datumových datových typů.Nejprve  jednoduchý příklad:

SET DATEFORMAT dmy
GO

DECLARE @Date DATETIME 
SET @Date = '31/12/2018 10:00:00'
SELECT @Date
GO

Zde vidíme, že vše dobře dopadlo. SQL Serveru jsme řekli, že na první pozici v řetězci se nacházejí dny a na druhé měsíce, a nebyl tedy s převodem žádný problém.  Hodnota 31 se správně převáděla na dny.

Nyní zkusme SQL Server zmást:

SET DATEFORMAT dmy
GO

DECLARE @Date DATETIME 
SET @Date = '12/31/2018 10:00:00'
SELECT @Date
GO

Zmatení se podařilo a nastala chyba, která neznamená nic jiného, než že zkrátka a dobře mají-li na druhé pozici v řetězci být měsíce, nemůže se tam ocitnout hodnota 31, protože maximální možné číslo měsíce je 12.

Ponechme tedy datum uložený v řetězci v původní podobě, ale změňme nastavení SET DATEFORMAT tak, aby odpovídalo skutečnému uspořádání řetězce, kdy měsíce přesuneme na první pozici před dny:

SET DATEFORMAT mdy
GO

DECLARE @Date DATETIME 
SET @Date = '12/31/2018 10:00:00'
SELECT @Date
GO

Vše proběhlo správně.

Pro každodenní použití je podstatné si uvědomit, že změny chování dosahujeme použitím SET příkazu pro celé aktivní připojení k SQL Serveru a platí všechny podmínky uvedené zde.

Pokud potřebujeme zjistit, jaké je aktuální stavení DATEFORMAT pro naše připojení (@@SPID), máme dvě možnosti: použít DBCC USEROPTIONS příkaz nebo dohledat příslušné nastavení daného připojení v systémových pohledech:

DBCC USEROPTIONS;
GO
SELECT date_format FROM sys.dm_exec_requests WHERE session_id = @@SPID
GO

V obecné rovině lze doporučit takové zacházení s datumovými hodnotami, aby nikdy nebylo nutné měnit nastavení DATEFORMAT, protože změnou nastavení připojení si vnášíme do systému určitou zbytečnou míru entropie, se kterou je třeba dále počítat.

Leave a Reply

Your email address will not be published. Required fields are marked *