sql >> Databasteknik >  >> RDS >> Sqlserver

Felsökning av problem när du arbetar med datum och tid i SQL Server

Microsoft SQL Server-databasen lagrar information om datum och tid i en mängd olika format. De vanligaste av dem är DateTime , DatumTime2 och Datum . Som det händer med alla typer av data kan problem uppstå gång på gång. I den här artikeln kommer vi att fokusera på att felsöka några av de vanligaste problemen som du kan möta när du arbetar med SQL-datatyperna för tid och datum.

Problem relaterade till regionalt olika datumformat

Formatet på datumen varierar globalt. Till exempel skriver britterna datum som dd-mm-åååå, medan amerikaner skriver datum i formatet mm-dd-åååå. På så sätt skrivs samma datum, 31 december 2020, som 31-12-2020 i det brittiska datumformatet och som 12-31-2020 i det amerikanska formatet.

Inkapabilitetsproblem kan uppstå om du inte anger datumet i ett format som motsvarar språkinställningarna för din SQL Server-instans.

Följande skript konverterar textsträngen med datuminformationen till formatet DATETIME. Språkinställningarna är inställda på BRITISH. Textsträngen innehåller 31-12-2020 04:25:30 .

Om du castar denna sträng till formatet DATETIME kommer 31 att behandlas som dag, medan 12 är månad som standard. Därför kommer konverteringen att lyckas som visas från utdata:

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

Men om du försöker konvertera strängen som innehåller datumet 31-12-2020 till formatet DATETIME med US_ENGLISH språkinställningar kommer du att få ett felmeddelande enligt nedan:

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

Felet uppstår eftersom språkinställningarna US_ENGLISH definierar 31 som en månad istället för en dag. Som månaden värdet kan inte vara större än 12, vi får värdefelet utanför intervallet .

Om du anger datumet som 12-31-2020 och sedan konverterar datumsträngen till DATETIME med US_ENGLISH-inställningarna, kommer du att se den lyckade konverteringen:

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

På samma sätt konverterar du 2020-12-31 datumsträngen under inställningen BRITISH orsakar också ett fel – 31 behandlas som en månad, det kan inte vara det.

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

För att konvertera ditt datum korrekt, oavsett språkinställningarna, kan du använda ISO-standarden 8601 för datumformat. För att följa denna standard, ange datumet som åååå-mm-ddThh:mm:ss .

Till exempel har datumsträngen 2020-12-31T04:25:30 konverterats till datatypen DATETIME under BRITISH-språkinställningarna:

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

Följande skript visar samma sträng konverterad till DATETIME med US_ENGLISH-inställningarna:

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

Tidszonsöverväganden

Du kanske vill utveckla några SQL Server-databasapplikationer för den globala publiken. För det kan du behöva lägga till tidszoninformation till datatyperna för datum och tid.

I SQL Server lagrar datatypen DATETIMEOFFSET information om datum och tid tillsammans med tidszonsförskjutningen. Tidszonsförskjutningen anges som UTC +/- antal timmar.

Till exempel använder följande skript metoden SYSDATETIMEOFFSET() för att hämta datum, tid och offsetinformation för systemet som kör din SQL Server-instans. Värdena som returneras av funktionen SYSDATETIMEOFFSET() lagras i DATETIMEOFFSET-typvariabeln @dateoffset. Värdet på @dateoffset-variabeln skrivs ut med hjälp av SELECT-satsen:

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

Nedanstående utgång visar se aktuellt datum och tid och offsetvärdet. I det här fallet är det +02:00.

Du kan också få endast offsetvärdet från variabeln DATETIMEOFFSET. För att göra det måste du skicka DATETIMEOFFSET-typvariabeln som det andra parametervärdet till DATENAME()-funktionen. Den första parametern till metoden DATENAME() ska vara tzoffset .

Följande skript returnerar tidsförskjutningsdelen av det aktuella systemdatumet:

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

För att skapa en anpassad DATETIMEOFFSET-variabel, ange värden för datum-, tid- och tidsförskjutningsdelarna. Till exempel, i följande skript, värdet för datumet är 2015-02-22 , värdet för tidsdelen är 23:59:59:999 och tidsförskjutningsvärdet är +05:00 .

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

Slutligen kan du också uppdatera informationen om tidsförskjutning med SWITCHOFFSET() funktion.

Du måste klara DATETIMEOFFSET skriv variabel som första parametervärde och skicka den nya tidsförskjutningen som andra parametervärde till SWITCHOFFSET funktion.

Följande skript uppdaterar tidsförskjutningsvärdet för variabeln DATETIMEOFFSET från +05:00 till +09:00.

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

Välja poster med BETWEEN Operator med DateTime

MELLAN operatorn i SQL-servern filtrerar posterna mellan värdeintervallet som skickas till den.

Du kan använda operatorn MELLAN för att returnera poster mellan två datum. Du bör dock vara extra försiktig när du använder den för att filtrera poster med datum.

Till exempel skapar följande skript en dummy Vandrarhem databas och lägger till en Student tabell till 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
)

Nästa skript lägger till några dummy-poster till eleven tabell. Födelsedatumet kolumnen Student tabell lagrar datum. Av detta manus kan man se att två elever Sara och Nik har samma födelsedatum. Födelsetiden är dock annorlunda:

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 kunna tro att BETWEEN-operatorn skulle kunna användas för att hämta journalerna för alla elever födda 2015-02-22.

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

Men om du kör ovanstående skript kommer du att se att endast en post returneras, trots tiden del ingår också.

Anledningen är att BETWEEN-operatören som standard behandlar DATETIME-värdet 2015-02-22 som 2015-02-22 00:00:00 . Därför sökte operatorn BETWEEN i ovanstående fråga efter posterna med Födelsedatum värde mellan 2015-02-22 00:00:00 och 2015-02-22 00:00:00 .

För att lösa det här problemet måste vi ange tidsdelen när vi använder operatorn BETWEEN med datatypen DATETIME.

Följande skript returnerar alla poster mellan 2015-02-22 00:00:00 och 2015-02-22 23:59:59:999 . Tidsdelen för den övre datumgränsen är 23:59:999.

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

I utgången får vi två poster för Födelsedatum 2015-02-22 .

Problem relaterade till datumintervall

Datatypen DATETIME stöder endast år 1753 till 9999. Därför, om du försöker lagra ett datum med ett årvärde som är större än 9999 eller mindre än 1753, får du ett felmeddelande.

Följande skript försöker konvertera 1392-12-31 datumsträng. 1392 är mindre än 1753. Därför har vi värdefelet utanför intervallet.

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

För att lagra årsvärden mindre än 1753 , kan du använda DATETIME2 data typ. Den lagrar årsvärden från 0000 till 9999.

Följande skript konverterar framgångsrikt datumsträngen 1392-12-31 till datatypen DATETIME2:

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

Använder TRY_COVERT för DateTime Conversion

KONVERTERA-funktionen i SQL Server konverterar data från en typ till en annan. Du kan använda den för att konvertera dataformaten av datumtyp till andra format och vice versa. Men om konverteringen misslyckas, ger funktionen KONVERTERA ett fel.

Till exempel konverterar vi strängen 2015-31-31 till formatet DATETIME:

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

Om du vill att ett NULL-värde ska returneras när konverteringen misslyckas istället för felmeddelandet, använd TRY_CONVERT fungera. Den här metoden låter inte programmet krascha – den returnerar helt enkelt ett NULL-värde.

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

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

Slutsats

När du arbetar med SQL Server kan du möta många problem som förstör din upplevelse och komplicerar uppgifterna. Att känna till de vanligaste problemen är å andra sidan den mest effektiva metoden för att förhindra att de inträffar. Det är därför vi dedikerade den här artikeln till att felsöka sådana besvär som kan uppstå under ditt arbete med information om datum och tider.

Observera också att moderna verktyg för att arbeta med SQL Server-databaser kan göra livet för DB-specialister mycket enklare. Speciellt tillhandahåller dbForge Studio för SQL Server funktionen Visual Data Editor som kan användas vid hantering av datum. Du kan använda den för att se och redigera datumen på det mest användarvänliga sättet.


  1. BEGIN - END block atomära transaktioner i PL/SQL

  2. Bästa sätten att reparera korrupt InnoDB-tabell i MySQL

  3. Hur man bestämmer tabellstorlek i Oracle

  4. Hur skulle du implementera sekvenser i Microsoft SQL Server?