sql >> Database teknologi >  >> RDS >> Sqlserver

Fejlfinding af problemer ved arbejde med dato og klokkeslæt i SQL Server

Microsoft SQL Server-databasen gemmer oplysninger om dato og klokkeslæt i en række forskellige formater. De mest almindelige af dem er DateTime , DateTime2 og Dato . Som det sker med alle typer data, kan der opstå problemer gang på gang. I denne artikel vil vi fokusere på fejlfinding af nogle af de mest almindelige problemer, som du kan komme ud for, mens du arbejder med SQL-tids- og datodatatyperne.

Problemer relateret til regionalt forskellige datoformater

Formatet på datoerne varierer globalt. For eksempel skriver briterne datoer som dd-mm-åååå, mens amerikanere skriver datoer i formatet mm-dd-åååå. På denne måde skrives den samme dato, 31. december 2020, som 31-12-2020 i det britiske datoformat og som 31-12-2020 i det amerikanske format.

Der kan opstå problemer med manglende evne, hvis du ikke angiver datoen i et format, der svarer til sprogindstillingerne for din SQL Server-instans.

Følgende script konverterer tekststrengen med datooplysningerne til DATETIME-formatet. Sprogindstillingerne er indstillet til BRITISH. Tekststrengen indeholder 31-12-2020 04:25:30 .

Hvis du kaster denne streng ind i DATETIME-formatet, vil 31 blive behandlet som dag, mens 12 vil være måned som standard. Derfor vil konverteringen lykkes som vist fra outputtet:

SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '31-12-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

Men hvis du prøver at konvertere strengen, der indeholder datoen 31-12-2020 til formatet DATETIME ved hjælp af US_ENGLISH sprogindstillinger, vil du modtage en fejl som vist nedenfor:

SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '31-12-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

Fejlen opstår, fordi sprogindstillingerne US_ENGLISH definerer 31 som en måned i stedet for en dag. Som måneden værdien må ikke være større end 12, vi modtager værdifejlen uden for området .

Hvis du angiver datoen som 31-12-2020 og derefter konverterer datostrengen til DATETIME ved hjælp af US_ENGLISH-indstillingerne, vil du se den vellykkede konvertering:

SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '12-31-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

På samme måde konverteres 12-31-2020 datostreng under indstillingen BRITISH forårsager også en fejl – 31 behandles som en måned, det kan ikke være det.

SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '12-31-2020 04:25:30';
SELECT CAST(@date AS DATETIME);

For at konvertere din dato nøjagtigt uanset sprogindstillingerne, kan du bruge ISO-standarden 8601 til datoformat. For at overholde denne standard skal du angive datoen som åååå-mm-ddThh:mm:ss .

For eksempel er datostrengen 2020-12-31T04:25:30 konverteret til datatypen DATETIME under BRITISH sprogindstillingerne:

SET LANGUAGE BRITISH;
DECLARE @date VARCHAR(50) = '2020-12-31T04:25:30';
SELECT CAST(@date AS DATETIME);

Følgende script viser den samme streng konverteret til DATETIME med US_ENGLISH-indstillingerne:

SET LANGUAGE US_ENGLISH;
DECLARE @date VARCHAR(50) = '2020-12-31T04:25:30';
SELECT CAST(@date AS DATETIME);

Tidszoneovervejelser

Du ønsker måske at udvikle nogle SQL Server-databaseapplikationer til det globale publikum. Til det skal du muligvis tilføje tidszoneoplysningerne til datatyperne for dato og klokkeslæt.

I SQL Server gemmer datatypen DATETIMEOFFSET dato- og tidsinformationen sammen med tidszoneforskydningen. Tidszoneforskydningen er angivet som UTC +/- antal timer.

For eksempel bruger følgende script metoden SYSDATETIMEOFFSET() til at hente dato, klokkeslæt og offsetoplysninger for det system, der kører din SQL Server-instans. Værdierne returneret af funktionen SYSDATETIMEOFFSET() gemmes i DATETIMEOFFSET typevariablen @dateoffset. Værdien af ​​@dateoffset-variablen udskrives ved hjælp af SELECT-sætningen:

DECLARE @dateoffset DATETIMEOFFSET = SYSDATETIMEOFFSET();
SELECT @dateoffset

Nedenstående output viser se den aktuelle dato og klokkeslæt og offsetværdien. I dette tilfælde er det +02:00.

Du kan også kun få offset-værdien fra DATETIMEOFFSET-variablen. For at gøre det skal du overføre DATETIMEOFFSET-typevariablen som den anden parameterværdi til DATENAME()-funktionen. Den første parameter til DATENAME()-metoden skal være tzoffset .

Følgende script returnerer tidsforskydningsdelen af ​​den aktuelle systemdato:

DECLARE @dateoffset DATETIMEOFFSET = SYSDATETIMEOFFSET();
SELECT DATENAME(tzoffset, @dateoffset)

For at oprette en tilpasset DATETIMEOFFSET-variabel skal du angive værdier for dato-, tidspunkt- og tidsforskydningsdelene. For eksempel, i det følgende script, værdien for datoen er 2015-02-22 , værdien for tidsdelen er 23:59:59:999 , og tidsforskydningsværdien er +05:00 .

DECLARE @dateoffset DATETIMEOFFSET = '2015-02-22 23:59:59:999 +05:00';
SELECT @dateoffset

Endelig kan du også opdatere informationen om tidsforskydning ved hjælp af SWITCHOFFSET() funktion.

Du skal bestå DATETIMEOFFSET skriv variabel som den første parameterværdi og overfør den nye tidsforskydning som den anden parameterværdi til SWITCHOFFSET funktion.

Følgende script opdaterer tidsforskydningsværdien for DATETIMEOFFSET-variablen fra +05:00 til +09:00.

DECLARE @dateoffset DATETIMEOFFSET = '2015-02-22 23:59:59:999 +05:00';
SELECT SWITCHOFFSET(@dateoffset, '+09:00');

Valg af poster ved hjælp af BETWEEN Operator med DateTime

MELLEM operatøren i SQL-serveren filtrerer posterne mellem de værdier, der sendes til den.

Du kan bruge BETWEEN-operatoren til at returnere poster mellem to datoer. Du bør dog være ekstra forsigtig, når du bruger den til at filtrere poster med datoer.

For eksempel opretter følgende script en dummy Hostel database og tilføjer en elev bord til det.

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
)

Det næste script tilføjer nogle dummy-poster til eleven bord. Fødselsdatoen kolonne i Student tabel gemmer datoer. Fra dette manuskript kan du se, at to elever Sara og Nik har samme fødselsdato. Fødselstidspunktet er dog anderledes:

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')

Man skulle tro, at BETWEEN-operatoren kunne bruges til at hente optegnelserne over alle elever født 2015-02-22.

SELECT * FROM Student
WHERE BirthDate BETWEEN '2015-02-22' AND '2015-02-22'

Men hvis du udfører ovenstående script, vil du se, at der kun returneres én post på trods af tidspunktet del er også inkluderet.

Årsagen er, at BETWEEN-operatøren som standard behandler DATETIME-værdien 2015-02-22 som 2015-02-22 00:00:00 . Derfor søgte BETWEEN-operatoren i ovenstående forespørgsel efter posterne med fødselsdatoen værdi mellem 2015-02-22 00:00:00 og 2015-02-22 00:00:00 .

For at løse dette problem skal vi angive tidsdelen, når vi bruger BETWEEN-operatoren med datatypen DATETIME.

Følgende script returnerer alle poster mellem 2015-02-22 00:00:00 og 2015-02-22 23:59:59:999 . Tidsdelen for den øvre datogrænse er 23:59:999.

SELECT * FROM Student
WHERE BirthDate BETWEEN '2015-02-22' AND '2015-02-22 23:59:59:999';

I outputtet får vi to poster for Fødselsdatoen 2015-02-22 .

Problemer relateret til datointervaller

Datatypen DATETIME understøtter kun år 1753 til og med 9999. Derfor, hvis du forsøger at gemme en dato med en årstal, der er større end 9999 eller mindre end 1753, får du en fejlmeddelelse.

Følgende script forsøger at konvertere 1392-12-31 dato streng. 1392 er mindre end 1753. Derfor har vi værdifejlen uden for området.

DECLARE @date VARCHAR(50) = '1392-12-31 04:25:30';
SELECT CAST(@date AS DATETIME);

For at gemme årstal mindre end 1753 , kan du bruge DATETIME2 datatype. Den gemmer årstal fra 0000 til 9999.

Følgende script konverterer med succes datostrengen 1392-12-31 til DATETIME2 datatype:

DECLARE @date VARCHAR(50) = '1392-12-31 04:25:30';
SELECT CAST(@date AS DATETIME2);

Brug af TRY_COVERT til DateTime-konvertering

KONVERTER-funktionen i SQL Server konverterer data fra én type til en anden. Du kan bruge den til at konvertere dataformater af datotype til andre formater og omvendt. Men hvis konverteringen mislykkes, giver funktionen KONVERTER en fejl.

For eksempel konverterer vi strengen 2015-31-31 til DATETIME-format:

DECLARE @date VARCHAR(50) = '2015-31-13';
SELECT  CONVERT(DATETIME, @date ,105) as DOB_CONV

Hvis du gerne vil have en NULL-værdi returneret, når konverteringen mislykkes i stedet for fejlmeddelelsen, skal du bruge TRY_CONVERT fungere. Denne metode vil ikke lade applikationen gå ned - den returnerer blot en NULL-værdi.

DECLARE @date VARCHAR(50) = '2015-31-13';

SELECT  TRY_CONVERT(DATETIME, @date ,105) as DOB_CONV

Konklusion

Når du arbejder med SQL Server, kan du stå over for mange problemer, der ødelægger din oplevelse og komplicerer opgaverne. At kende de mest almindelige problemer er på den anden side den mest effektive metode til at forhindre dem i at ske. Det er derfor, vi har dedikeret denne artikel til at fejlfinde sådanne gener, der kan opstå under dit arbejde med oplysningerne om datoer og tidspunkter.

Bemærk også, at moderne værktøjer til at arbejde med SQL Server-databaser kan gøre livet for DB-specialister meget enklere. Især giver dbForge Studio til SQL Server funktionen Visual Data Editor, som kan anvendes, når der håndteres datoer. Du kan bruge den til at se og redigere datoerne på den mest brugervenlige måde.


  1. Hvordan Width_Bucket() virker i PostgreSQL

  2. Hvordan DevOps skal bruge DBaaS (Database-as-a-Service) til at optimere deres applikationsudvikling​

  3. Forskellen mellem VARCHAR og TEXT i MySQL

  4. Sådan genereres DB-testdata