Databáze Microsoft SQL Server ukládá informace o datu a čase v různých formátech. Nejběžnější z nich jsou Datum a čas , Datum a čas2 a Datum . Stejně jako u všech typů dat se problémy mohou vyskytnout čas od času. V tomto článku se zaměříme na řešení některých nejběžnějších problémů, se kterými se můžete setkat při práci s datovými typy SQL pro čas a datum.
Problémy související s regionálně odlišnými formáty data
Formát dat se globálně liší. Například Britové píší data jako dd-mm-yyyy, zatímco Američané píší data ve formátu mm-dd-rrrr. Tímto způsobem se stejné datum, 31. prosinec 2020, zapíše jako 31-12-2020 v britském formátu data a jako 12-31-2020 v americkém formátu.
Pokud neurčíte datum ve formátu odpovídajícím jazykovému nastavení vaší instance SQL Server, mohou nastat problémy s neschopností.
Následující skript převede textový řetězec s informací o datu do formátu DATETIME. Nastavení jazyka je nastaveno na BRITISH. Textový řetězec obsahuje 31-12-2020 04:25:30 .
Pokud přenesete tento řetězec do formátu DATETIME, bude 31 považováno za den, zatímco 12 bude ve výchozím nastavení měsíc. Převod tedy bude úspěšný, jak ukazuje výstup:
SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '31-12-2020 04:25:30';
SELECT CAST(@date AS DATETIME);
Pokud se však pokusíte převést řetězec obsahující datum 31-12-2020 do formátu DATETIME pomocí US_ENGLISH nastavení jazyka, zobrazí se níže uvedená chyba:
SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '31-12-2020 04:25:30';
SELECT CAST(@date AS DATETIME);
K chybě dochází, protože nastavení jazyka US_ENGLISH definuje 31 jako měsíc místo dne. Jako měsíc hodnota nemůže být větší než 12, dostáváme chybu hodnoty mimo rozsah .
Pokud zadáte datum jako 12-31-2020 a poté převedete řetězec data na DATETIME pomocí nastavení US_ENGLISH, uvidíte úspěšný převod:
SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '12-31-2020 04:25:30';
SELECT CAST(@date AS DATETIME);
Podobně převod 31. 12. 2020 řetězec data pod nastavením BRITISH jazyka také způsobuje chybu – 31 je považováno za měsíc, to nemůže být.
SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '12-31-2020 04:25:30';
SELECT CAST(@date AS DATETIME);
Chcete-li převést datum přesně bez ohledu na nastavení jazyka, můžete použít normu ISO 8601 pro formát data. Chcete-li dodržet tento standard, zadejte datum jako rrrr-mm-ddThh:mm:ss .
Například datový řetězec 2020-12-31T04:25:30 byl úspěšně převeden na datový typ DATETIME v nastavení BRITISH language:
SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '2020-12-31T04:25:30';
SELECT CAST(@date AS DATETIME);
Následující skript zobrazuje stejný řetězec převedený na DATETIME s nastavením US_ENGLISH:
SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '2020-12-31T04:25:30';
SELECT CAST(@date AS DATETIME);
Úvahy o časovém pásmu
Možná budete chtít vyvinout některé databázové aplikace SQL Server pro globální publikum. K tomu možná budete muset přidat informace o časovém pásmu k datovým typům data a času.
V SQL Server datový typ DATETIMEOFFSET ukládá informace o datu a čase spolu s posunem časového pásma. Posun časového pásma je zadán jako počet hodin UTC +/-.
Například následující skript používá metodu SYSDATETIMEOFFSET() k získání informací o datu, čase a posunu systému, na kterém běží vaše instance SQL Server. Hodnoty vrácené funkcí SYSDATETIMEOFFSET() jsou uloženy v proměnné typu DATETIMEOFFSET @dateoffset. Hodnota proměnné @dateoffset se vytiskne pomocí příkazu SELECT:
DECLARE @dateoffset DATETIMEOFFSET = SYSDATETIMEOFFSET();
SELECT @dateoffset
Níže uvedený výstup ukazuje aktuální datum a čas a hodnotu offsetu. V tomto případě je to +02:00.
Můžete také získat pouze hodnotu offsetu z proměnné DATETIMEOFFSET. Chcete-li tak učinit, musíte funkci DATENAME() předat proměnnou typu DATETIMEOFFSET jako druhou hodnotu parametru. První parametr metody DATENAME() by měl být tzoffset .
Následující skript vrací část časového posunu aktuálního systémového data:
DECLARE @dateoffset DATETIMEOFFSET = SYSDATETIMEOFFSET();
SELECT DATENAME(tzoffset, @dateoffset)
Chcete-li vytvořit vlastní proměnnou DATETIMEOFFSET, zadejte hodnoty pro části data, času a časového posunu. Například v následujícím skriptu hodnota pro datum je 22. 2. 2015 , hodnota pro časovou část je 23:59:59:999 a hodnota časového posunu je +05:00 .
DECLARE @dateoffset DATETIMEOFFSET = '2015-02-22 23:59:59:999 +05:00';
SELECT @dateoffset
Nakonec můžete také aktualizovat informace o časovém posunu pomocí SWITCHOFFSET() funkce.
Musíte projít DATETIMEOFFSET zadejte proměnnou jako první hodnotu parametru a předejte nový časový posun jako druhou hodnotu parametru do SWITCHOFFSET funkce.
Následující skript aktualizuje hodnotu časového posunu pro proměnnou DATETIMEOFFSET z +05:00 na +09:00.
DECLARE @dateoffset DATETIMEOFFSET = '2015-02-22 23:59:59:999 +05:00';
SELECT SWITCHOFFSET(@dateoffset, '+09:00');
Výběr záznamů pomocí operátoru BETWEEN s datem a časem
MEDZI operátor na serveru SQL filtruje záznamy mezi rozsahem hodnot, které mu byly předány.
Pomocí operátoru BETWEEN můžete vrátit záznamy mezi dvěma daty. Při jeho použití pro filtrování záznamů s daty byste však měli být obzvláště opatrní.
Například následující skript vytvoří fiktivní hostel databázi a přidá jednoho Studenta stůl k tomu.
CREATE DATABASE Hostel
USE Hostel
CREATE TABLE Student
(
Id INT PRIMARY KEY IDENTITY(1,1),
Name VARCHAR (50) NOT NULL,
Gender VARCHAR (50),
BirthDate DateTime
)
Další skript přidá nějaké fiktivní záznamy do Student stůl. Datum narození sloupec Student tabulka ukládá data. Z tohoto skriptu můžete vidět, že dvě studentky Sara a Nik mají stejná data narození. Doba narození je však jiná:
INSERT INTO Student
VALUES ('Jack', 'Male', '2017-06-30 16:30:35'),
('Sara', 'Female', '2015-02-22 00:00:00'),
('Elisa', 'Female', '2020-03-16 22:24:39'),
('Nik', 'Male', '2015-02-22 09:45:55'),
('Jos', 'Male', '2015-03-25 11:55:20')
Mysleli byste si, že operátor BETWEEN lze použít k načtení záznamů všech studentů narozených 22. 2. 2015.
SELECT * FROM Student
WHERE BirthDate BETWEEN '2015-02-22' AND '2015-02-22'
Ale pokud spustíte výše uvedený skript, uvidíte, že se vrátí pouze jeden záznam, a to navzdory času část je také zahrnuta.
Důvodem je, že operátor BETWEEN ve výchozím nastavení zachází s hodnotou DATETIME 2015-02-22 jako 2015-02-22 00:00:00 . Proto operátor BETWEEN ve výše uvedeném dotazu hledal záznamy s Datum narození hodnota mezi 2015-02-22 00:00:00 a 2015-02-22 00:00:00 .
Abychom tento problém vyřešili, musíme určit časovou část při použití operátoru BETWEEN s datovým typem DATETIME.
Následující skript vrátí všechny záznamy mezi 2015-02-22 00:00:00 a 2015-02-22 23:59:59:999 . Čas pro horní limit data je 23:59:999.
SELECT * FROM Student
WHERE BirthDate BETWEEN '2015-02-22' AND '2015-02-22 23:59:59:999';
Ve výstupu získáme dva záznamy pro Datum narození – 22. 2. 2015 .
Problémy související s časovými obdobími
Datový typ DATETIME podporuje pouze roky 1753 až 9999. Pokud se tedy pokusíte uložit datum s hodnotou roku větší než 9999 nebo menší než 1753, zobrazí se chyba.
Následující skript se pokusí převést 1392-12-31 datový řetězec. 1392 je menší než 1753. Máme tedy chybu hodnoty mimo rozsah.
DECLARE @date VARCHAR(50) = '1392-12-31 04:25:30';
SELECT CAST(@date AS DATETIME);
Chcete-li uložit hodnoty roku méně než 1753 , můžete použít DATETIME2 datový typ. Ukládá hodnoty roku od 0000 do 9999.
Následující skript úspěšně převede datový řetězec 1392-12-31 na datový typ DATETIME2:
DECLARE @date VARCHAR(50) = '1392-12-31 04:25:30';
SELECT CAST(@date AS DATETIME2);
Použití TRY_COVERT pro převod data a času
Funkce CONVERT v SQL Server převádí data z jednoho typu na jiný. Můžete jej použít pro převod datových formátů typu data do jiných formátů a naopak. Pokud se však převod nezdaří, funkce CONVERT vyvolá chybu.
Například převádíme řetězec 2015-31-31 do formátu DATETIME:
DECLARE @date VARCHAR(50) = '2015-31-13';
SELECT CONVERT(DATETIME, @date ,105) as DOB_CONV
Pokud chcete, aby se při selhání převodu namísto chybové zprávy vrátila hodnota NULL, použijte TRY_CONVERT funkce. Tato metoda nedovolí, aby se aplikace zhroutila – jednoduše vrátí hodnotu NULL.
DECLARE @date VARCHAR(50) = '2015-31-13';
SELECT TRY_CONVERT(DATETIME, @date ,105) as DOB_CONV
Závěr
Při práci se serverem SQL můžete čelit mnoha problémům, které kazí vaše zkušenosti a komplikují úkoly. Znát nejčastější potíže je na druhou stranu nejúčinnější metodou, jak jim předcházet. Proto jsme tento článek věnovali řešení takových nepříjemností, které se mohou vyskytnout při práci s informacemi o datech a časech.
Všimněte si také, že moderní nástroje pro práci s databázemi SQL Server mohou výrazně zjednodušit život DB specialistů. Konkrétně dbForge Studio pro SQL Server poskytuje funkci Visual Data Editor, kterou lze použít při práci s daty. Můžete jej použít k zobrazení a úpravě dat uživatelsky nejpřívětivějším způsobem.