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

datetime vs smalldatetime i SQL Server:Hvad er forskellen?

Denne artikel udforsker de vigtigste forskelle mellem dato og klokkeslæt og smalldatetime datatyper i SQL Server.

Begge datatyper bruges til at gemme dato- og tidsværdier, men der er forskelle mellem de to. I de fleste tilfælde er det bedre at undgå begge typer og bruge datetime2 i stedet (Microsoft anbefaler også dette). Under alle omstændigheder er her en sammenligning af disse to datatyper.

Følgende tabel skitserer nogle vigtige ligheder og forskelle mellem disse to datatyper.

Funktion smalldatetime datotid
SQL-kompatibel (ANSI &ISO 8601) Nej Nej
Datointerval 1900-01-01 til 2079-06-06 1753-01-01 til 9999-12-31
Tidsinterval 00:00:00 til 23:59:59 00:00:00 til 23:59:59.997
Tegnlængde 19 positioner maksimum 19 positioner minimum
23 maksimum
Lagerstørrelse 4 bytes, rettet 8 bytes, rettet
Nøjagtighed Et minut Afrundet til trin på 0,000, 003 eller 0,007 sekunder
Brøksekundpræcision Nej Ja
Brugerdefineret brøksekundpræcision Nej Nej
Tidszoneforskydning Ingen Ingen
Opmærksomhed og bevarelse af tidszoneforskydning Nej Nej
Sommertid opmærksom på Nej Nej

Skal jeg bruge 'datetime' eller 'smalldatetime'?

Microsoft fraråder at bruge begge disse datatyper til nyt arbejde. Du bør kun bruge dem, hvis du har en stærk grund til det.

Men hvis du skulle vælge, ville din beslutning sandsynligvis blive truffet ved at opveje den ekstra præcision og nøjagtighed af datetime i forhold til de lavere lagerkrav for smalldatetime .

Med andre ord, hvis du ikke har brug for nøjagtighed til sekunder, smalldatetime vil gøre arbejdet, mens du kun bruger halvdelen af ​​lagerpladsen. På den anden side, hvis du har brug for nøjagtighed til sekunderne (eller endda nogle brøkdele sekunder), så skal du bruge datetime .

Under alle omstændigheder anbefaler Microsoft at bruge dato , tid , datetime2 eller datotidsforskydning til nyt arbejde.

Se smalldatetime vs datetime2 og datotid vs datetime2 for at se, hvordan hver af disse typer sammenlignes med datetime2 .

Eksempel 1 – Grundlæggende sammenligning

Her er et hurtigt eksempel til at demonstrere den grundlæggende forskel mellem datetime og smalldatetime .

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.555';
SET @thesmalldatetime = @thedatetime;
SELECT 
  @thedatetime AS 'datetime',
  @thesmalldatetime AS 'smalldatetime';

Resultat:

+-------------------------+---------------------+
| datetime                | smalldatetime       |
|-------------------------+---------------------|
| 2025-05-21 10:15:30.557 | 2025-05-21 10:16:00 |
+-------------------------+---------------------+

Her indstiller jeg en smalldatetime variabel til samme værdi som datetime variabel. Dette får værdien til at blive konverteret til smalldatetime og vi kan derefter bruge en SELECT sætning for at se den faktiske værdi, der blev tildelt hver variabel.

I dette tilfælde runder begge variable værdien op. Men de er afrundet anderledes.

datoen variabel runder brøksekunderdelen op. Dette er fordi datetime afrunder altid til trin på 0,000, 003 eller 0,007 sekunder.

smalldatetime variabel på den anden side runder minutterne op en del. Ikke nok med det, sekunder-delen er sat til nul. Dette kan forventes, fordi Microsofts officielle dokumentation siger, at smalldatetime 's tid er ...baseret på en 24-timers dag, med sekunder altid nul (:00) og uden brøkdele af sekunder .

Så vi kan se, at datetime type giver en mere præcis og nøjagtig dato/tidsværdi.

Eksempel 2 – Indstilling af værdier fra strenge bogstaver

I de foregående eksempler er smalldatetime værdien blev tildelt ved at indstille den til samme værdi som datetime værdi. Når vi gør det, udfører SQL Server en implicit konvertering for at dataene "passer" til den nye datatype.

Som det viser sig, kan vi også indstille smalldatetime variabel til den samme strengliteral, der inkluderer brøksekunder (selvom denne datatype ikke gemmer brøksekunder).

Her er et eksempel, hvor jeg gør netop det:

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.555';
SET @thesmalldatetime = '2025-05-21 10:15:30.555';
SELECT 
  @thedatetime AS 'datetime',
  @thesmalldatetime AS 'smalldatetime';

Resultat:

+-------------------------+---------------------+
| datetime                | smalldatetime       |
|-------------------------+---------------------|
| 2025-05-21 10:15:30.557 | 2025-05-21 10:16:00 |
+-------------------------+---------------------+

Selvfølgelig er resultatet det samme, når vi vælger værdierne – smalldatetime værdien viser ikke nogen brøksekunder, sekunderne er nul, og minutterne rundes op.

Men hvis vi bruger mere end 3 decimaler, vil begge datatyper returnere en fejl.

Fejl for datetime :

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.5555';
SET @thesmalldatetime = '2025-05-21 10:15:30.5555';
SELECT 
  @thedatetime AS 'datetime',
  @thesmalldatetime AS 'smalldatetime';

Resultat:

Msg 241, Level 16, State 1, Line 4
Conversion failed when converting date and/or time from character string.

Fejl for smalldatetime :

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.5555';
SET @thesmalldatetime = '2025-05-21 10:15:30.5555';
SELECT 
  @thedatetime AS 'datetime',
  @thesmalldatetime AS 'smalldatetime';

Resultat:

Msg 295, Level 16, State 3, Line 5
Conversion failed when converting character string to smalldatetime data type.

Eksempel 3 – Lagerstørrelse

smalldatetime datatypen har en fast lagerstørrelse på 4 bytes. Dette er en af ​​de få fordele smalldatetime har over datetime , som har en fast lagerstørrelse på 8 bytes.

Vi kan kontrollere lagerstørrelsen ved hjælp af DATALENGTH() funktion til at returnere antallet af bytes brugt for hver af vores værdier:

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.123';
SET @thesmalldatetime = @thedatetime;
SELECT 
  DATALENGTH(@thedatetime) AS 'datetime',
  DATALENGTH(@thesmalldatetime) AS 'smalldatetime';

Resultat

+------------+-----------------+
| datetime   | smalldatetime   |
|------------+-----------------|
| 8          | 4               |
+------------+-----------------+

Vi får også det samme resultat, selvom vi konverterer dem til varbinary , hvilket er mere repræsentativt for, hvordan de faktisk er gemt i databasen:

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.123';
SET @thesmalldatetime = @thedatetime;
SELECT 
  DATALENGTH(CAST(@thedatetime AS varbinary(10))) AS 'datetime',
  DATALENGTH(CAST(@thesmalldatetime AS varbinary(10))) AS 'smalldatetime';

Resultat

+------------+-----------------+
| datetime   | smalldatetime   |
|------------+-----------------|
| 8          | 4               |
+------------+-----------------+

  1. Ignorerer tidszoner helt i Rails og PostgreSQL

  2. MySQL-opdatering CASE HVORNÅR/SÅ/ANDEN

  3. Konverter 'datetime2' til 'datetime offset' i SQL Server (T-SQL-eksempler)

  4. Tips til læse-/skrivelåse afhængigt af transaktionsisolationsniveau i MSSQL