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

Odstraňování problémů při práci s datem a časem na serveru SQL Server

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.


  1. MYSQL importuje data z csv pomocí LOAD DATA INFILE

  2. Určení, zda jsou pole Data v Oracle typu Number

  3. 11 Doporučené postupy indexu SQL Server pro lepší ladění výkonu

  4. Jak nasadit aplikaci s databází serveru SQL na klientech