Typy daty i czasu w SQL Server

·

·

, ,
DatetimeTypesInSQL_00

Artykuł ten jest częścią serii Od 0 do TSQL którą znajdziesz tutaj.

Po typach tekstowych oraz liczbowych przyszła pora na omówienie typów daty i czasu. Część z Was może pomyśleć, iż datę i czas można przechowywać jako wartość liczbową? Generalnie jest to możliwe – pozbawiamy się wtedy jednak możliwości jakie oferuje użytkowanie typów przeznaczonych do tego typu danych.

W SQL Server mamy wbudowanych wiele typów związanych z datą i czasem, oto one:

  • date
  • datetime
  • datetime2
  • smalldatetime
  • time
  • datetimeoffset

Najprostszym z nich jest wspomniany na liście typ date. Jak można się domyśleć typ ten przechowuje datę. W ramach obiektu o tym typie możemy przechowywać daty od 0001-01-01 do 9999-12-31, gdzie jeden taki wpis zajmuje zawsze 3 bajty. Jeżeli chodzi
o format danych wstawianych do takiego pola to zależy on od ustawień serwera – jednak jeżeli podamy wartość daty w formacie ‘YYYYMMDD’ to zostanie on dostosowany do ustawień lokalnych – warto więc zapamiętać ten format i stosować go w większości przypadków.

Kolejnym równie prostym typem danych jest datetime. Jak sama nazwa wskazuje przechowuje on nie tylko datę, ale również czas. Pozwala na przechowywanie dat pochodzących z zakresu od 1753-01-01 do 9999-12-31 wraz z dowolną godziną aż do części milisekundowych. Typ ten zajmuje aż 8 bajtów co jest dosyć dużym rozmiarem.
W przypadku gdy nie jest nam potrzebna tak duża dokładność jaką oferuje nam datetime to warto zastosować bardzo zbliżony typ tj.  smalldatetime, który zajmuje 4 bajty ale pozwala na przechowywanie dat o dużo mniejszym zakresie tj. od 1900-01-01 do 2079-06-06. Jeżeli chodzi o czas to z smalldatetime tym wiąże się również bardzo ciekawa właściwość, którą postaram się zobrazować poniżej.

W ramach dowolnej bazy zadeklarujmy sobie zmienną przypiszmy do niej pełną datę i czas oraz wyświetlmy jej zawartość.

DECLARE @smalldatetime SMALLDATETIME

SET @smalldatetime='20150101 23:51:51'

PRINT	@smalldatetime

Jaką wartość wyświetli nam SQL Server? Dosyć nieoczekiwaną:

Jan  1 2015 11:52PM

Jak widać nie ma zdefiniowanych części sekundowych godziny, a część minutowa została zaokrąglona. Jest to normalne zachowanie tego typu danych, który zawsze należy mieć w tyle głowy w momencie gdy chcemy go użyć.

Co natomiast w przypadku gdy nie jest dla nas istotna dla nas data a jedynie czas? SQL Server daje nam możliwość przechowywania samego czasu i obok wspomnianych typów  mamy również typ time pozwalający przechowywać czas w oparciu o zegar 24 godzinny, aż do poziomu nanosekund. Poziom części sekund oczywiście jesteśmy w stanie kontrolować podając go jako parametr tj. np. time(7) oznacza właśnie poziom nanosekund – najbardziej szczegółowy. W zależności od szczegółowości typ ten zajmuje określoną ilość miejsca zgodnie z tabelą:

Zdefiniowany typ (precyzja,skala) Ilość bajtów
time (16,7) 5
time(0) (8,0) 3
time(1) (10,1) 3
time(2) (11,2) 3
time(3) (12,3) 4
time(4) (13,4) 4
time(5) (14,5) 5
time(6) (15,6) 5
time(7) (16,7) 5

Typ ten ma szczególne zastosowanie w momencie gdy chcemy przechowywać bardzo szczegółowe dane godzinowe, lub gdy chcemy z jakichś powodów oddzielić godzinę od daty. Podobnym pod względem dokładności godziny jest typ datetime2, który jest standardowym połączeniem typów datetime i time, a co za tym idzie również pozwala na zdefiniowanie poziomu szczegółowości godziny i zajmuje maksymalnie do 8 bajtów.

Ostatnim typem jaki sobie wyjaśnimy jest typ datetimeoffset, który pozwala na zapis daty i czasu wraz z uwzględnieniem strefy czasowej.  Wstawiając wartości do obiektu możemy użyć następującego domyślnego formatu YYYY-MM-DD hh:mm:ss[.nnnnnnn] [{+|-}hh:mm] czyli np.  ‘2015-12-31 23:59:10 +01:00’ oznacza przesunięcie o 1 godzinę do przodu w stosunku do UTC czyli standardowego czasu europejskiego. Przesunięcie może być zdefiniowane jako godzina oscylująca od -14:00 do +14:00. Typ ten jest bardzo pomocny w przypadku gdy dane w naszej bazie obejmują różne strefy czasowe, w innym wypadku powinniśmy go unikać gdyż posiada on dokładność taką jak datetime2 powiększoną właśnie o strefy czasowe i zajmuje w zależności od szczegółowości od 8 do 10 bajtów. W następnym artykule w ramach serii zajmiemy się funkcjami dostępnymi w ramach SQL Server, które pozwalają operować na konkretnych wartościach związanych z typami danych – ZAPRASZAM!

Adrian Chodkowski
Follow me
Latest posts by Adrian Chodkowski (see all)


Leave a Reply

4 responses to “Typy daty i czasu w SQL Server”
  1. Artur Avatar
    Artur

    Dzień Dobry
    a jak sformatować datę , żeby była wyświetlana w takim formacie i była liczbą?
    2019-08-05 12:17

    (select top 1 (CAST(CAST (TZ.DATACZAS_DO as date) as varchar(10)))+’ ‘+(CAST(CAST (TZ.DATACZAS_DO as time) as varchar(5))) from T_TACHO_ZDARZENIA TZ with(nolock) where tz.ID_KIEROWCY = kierowcy.id_kierowcy order by tz.DATACZAS_DO DESC) as [Ostatnia_data_logowania]
    ale to mi daje tekst 🙂

    Dzięki za info

    1. Adrian Chodkowski Avatar
      Adrian Chodkowski

      Witam,

      tą datę chce Pan mieć jako liczbę? 201908051217? jeśli tak to polecam zapoznać się z funkcją FORMAT, która co prawda zwraca tekst ale można to później formatować jako liczbę.

  2. miks Avatar
    miks

    Jak zapisać datę przed naszą erą? (BC)??????

    1. Adrian Chodkowski Avatar
      Adrian Chodkowski

      Niestety żadeń z wbudowanych typów data/czas nie ma tak szerokiego zakresu.

      W takim wypadku musimy albo trzymać rok/miesiąc/dzień w osobnych kolumnach albo stowrzyć swój własny typ na podstawie typu tekstowego:
      https://docs.microsoft.com/en-us/sql/relational-databases/clr-integration-database-objects-user-defined-types/working-with-user-defined-types-in-sql-server?view=sql-server-ver15