SQL Server 2016 – nowe funkcje daty czasu DATEDIFF_BIG oraz AT TIME ZONE

Każdy z nas zdaje sobie sprawę jak elementarne i ważne w bazach danych są dane daty i czasu. Można powiedzieć, że na przestrzeni kolejnych edycji SQL Server wiele zostało poprawione i udoskonalone – nie inaczej było z SQL Server 2016. W ramach niniejszego artykułu postaram się wskazać nowe funkcjonalności związane z datą i czasem, które będą przydatne w naszej codziennej, bazodanowej pracy – zapraszam!

Pierwszą funkcją, która została niejako rozszerzona jest popularne DATEDIFF, która jak zapewne wiecie oblicza różnicę pomiędzy określonymi datami w określonych jednostkach czasu jak np. dzień, miesiąc, rok i tym podobne. Funkcja ta zwraca typ Integer tak więc funkcja ta może zwrócić liczbę mieszczącą się w 4 bajtach tj. do –2,147,483,648 do 2,147,483,647. Co w przypadku gdy przekroczymy ten limit? Oczywiście pojawi się błąd! W waszych głowach może pojawić się myśl w jakich warunkach można taki zakres przekroczyć? Myślę, że w tak dynamicznie i precyzyjnie mierzonych przypadkach jakie występują w dzisiejszych czasach takie przekroczenie jak najbardziej jest możliwe. Sprawdźmy to na przykładzie – zadeklarujmy zmienną StartDate oraz EndDate, które będą odpowiadać za początek i koniec okresu. Pod StartDate przypiszemy rok 1 stycznia 1990 godzina 12, natomiast za EndDate posłuży nam bieżąca data i czas. Przypuśćmy, że chcemy obliczyć różnicę między tymi datami w…  sekundach.

USE tempdb
GO

DECLARE @StartDate datetime='19000101 12:00'
DECLARE @EndDate datetime=GETDATE()

SELECT DATEDIFF(SECOND,@StartDate,@EndDate)

Po wykonaniu powyższej komendy pojawi nam się komunikat błędu o treści:

Msg 535, Level 16, State 0, Line 7
The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. 
Try to use datediff with a less precise datepart.

SQL Server sugeruje nam żeby zmniejszyć precyzję interwału, który chcemy policzyć.. Oczywiście możecie powiedzieć, że przykład jest nierealistyczny i nie spotkacie się z nim w praktyce – ale czy na pewno? Możliwe, że będziecie musieli obliczyć różnicę w mikro czy nanosekundach, a tam nie potrzeba aż tak szerokiego zakresu aby wyjść poza ramy standardowego typu Integer. W tej sytuacji problem został rozwiązany dopiero w SQL Server 2016 gdyż do dyspozycji dostajemy funkcję DATEDIFF_BIG, która jest przeciążoną wersją DATEDIFF i zwraca typ BIGINT. Zobaczmy jej działanie w akcji – uruchomimy wcześniejsze zapytanie wykorzystując nową funkcję i dorzucając różnicę pomiezy datami w nanosekundach:

USE tempdb
GO

DECLARE @StartDate datetime='19000101 12:00'
DECLARE @EndDate datetime=GETDATE()

SELECT DATEDIFF_BIG(SECOND,@StartDate,@EndDate) AS DateDiffInSeconds,
	   DATEDIFF_BIG(NANOSECOND,@StartDate,@EndDate) AS DateDiffInNanoSeconds

datediff_big

Działa dokładnie tak jak chcieliśmy. To oczywiście nie jedyna nowość dostępna w SQL Server 2016 – kolejna z nich związana jest ze strefami czasowymi. Dotychczas żeby obliczać czas w innych strefach czasowych musieliśmy dodawać do określonej daty w strefie czasowej określoną liczbę godzin. W rezultacie istniała potrzeba przechowywania każdej danej czasu w formacie lokalnym oraz UTC. Ponadto nie było mechanizmu, który wprost obsługiwał czas letni – możecie sobie wyobrazić jak wiele problemów to przysparzało. Od SQL Server2016 mamy dużo łatwiejsze pole manewru ponieważ do dyspozycji oddany nam został widok systemowy o nazwie sys.time_zone_info, który zawiera informacje na temat wszystkich stref czasowych – sprawdźmy to konstruując prosty SELECT:

SELECT *
FROM
    sys.time_zone_info

time_zones

Jak można zauważyć na powyższym zrzucie ekranowym widok jest bardzo prosty i składa się z trzech kolumn tj. nazwy strefy czasowej, przesunięciu w stosunku do strefy UTC oraz wskaźnika czy w danej strefie obowiązuje czas letni. Widok bardzo pomocny ale jak możemy go użyć w praktyce? Korzystając ze specjalnej składni AT TIME ZONE, która konwertuje określoną datę na zapis datetimeoffset podkreślający przesunięcie czasowe:

SELECT 
	GETDATE() AS GetDate,
	GETDATE() AT TIME ZONE 'Cen. Australia Standard Time' AS 'Cen. Australia Standard Time'

datetimeoffsetattimezone

Oczywiście wcale nie musimy pamiętać nazw każdej ze stref wystarczy skorzystać z wcześniej wspomnianego widoku. Dzięki temu mechanizmowi mamy rozwiązane naprawdę wiele problemów związanych z systemami posiadającymi dane z wielu stref czasowych. To by było na tyle jeśli chodzi o nowości związane z datą i czasem w najnowszym wydaniu SQL Server. Może się wydawać, że nie ma tego dużo jednakże w tym wypadku są to naprawdę ogromnie wyczekiwane zmiany, które niejednemu programiście znacznie uprości życie.

 

Leave a Reply