sql >> Database >  >> RDS >> Sqlserver

SqlDateTime.MinValue !=DateTime.MinValue, waarom?

Ik denk dat het verschil tussen SQL's en .NET's Datum datatypes komt voort uit het feit dat SQL Server's datetime gegevenstype, de minimum- en maximumwaarden en de precisie ervan zijn veel ouder dan het DateTime-gegevenstype van .NET.

Met de komst van .NET besloot het team dat het datatype Datetime een meer natuurlijke zou moeten hebben. minimumwaarde, en 01/01/0001 lijkt een redelijk logische keuze, en zeker uit een programmeertaal , in plaats van database perspectief is deze waarde natuurlijker.

Overigens zijn er met SQL Server 2008 een aantal nieuwe op datum gebaseerde datatypes (Date, Time, DateTime2, DateTimeOffset) die daadwerkelijk een groter bereik en precisie bieden, en nauw aansluiten bij het DateTime datatype in .NET. Het gegevenstype DateTime2 heeft bijvoorbeeld een datumbereik van 0001-01-01 tot 9999-12-31.

Het standaard datatype "datetime" van SQL Server heeft altijd een minimumwaarde van 01/01/1753 gehad (en heeft dat inderdaad nog steeds!). Ik moet toegeven dat ik ook nieuwsgierig was naar de betekenis van deze waarde, dus ik heb wat gegraven.. Wat ik vond was als volgt:

Gedurende de periode tussen 1 na Christus en vandaag heeft de westerse wereld eigenlijk twee hoofdkalenders gebruikt:de Juliaanse kalender van Julius Caesar en de Gregoriaanse kalender van paus Gregorius XIII. De twee kalenders verschillen met betrekking tot slechts één regel:de regel om te beslissen wat een schrikkeljaar is. In de Juliaanse kalender zijn alle jaren die deelbaar zijn door vier schrikkeljaren. In de Gregoriaanse kalender zijn alle jaren die deelbaar zijn door vier schrikkeljaren, behalve dat jaren die deelbaar zijn door 100 (maar niet deelbaar door 400) geen schrikkeljaren zijn. Zo zijn de jaren 1700, 1800 en 1900 schrikkeljaren in de Juliaanse kalender, maar niet in de Gregoriaanse kalender, terwijl de jaren 1600 en 2000 schrikkeljaren zijn in beide kalenders.

Toen paus Gregorius XIII zijn kalender in 1582 introduceerde, gebood hij ook dat de dagen tussen 4 oktober 1582 en 15 oktober 1582 moesten worden overgeslagen - dat wil zeggen, hij zei dat de dag na 4 oktober 15 oktober zou moeten zijn. Veel landen vertraagd omschakelen, dat wel. Engeland en haar koloniën schakelden pas in 1752 over van Juliaanse naar Gregoriaanse berekening, dus voor hen waren de overgeslagen data tussen 4 september en 14 september 1752. Andere landen schakelden op andere tijden over, maar 1582 en 1752 zijn de relevante data voor de DBMS'en die we bespreken.

Er doen zich dus twee problemen met datumberekeningen voor wanneer men vele jaren teruggaat. De eerste is, moeten schrikkeljaren voordat de overstap wordt berekend volgens de Juliaanse of de Gregoriaanse regels? Het tweede probleem is:wanneer en hoe moeten de overgeslagen dagen worden afgehandeld?

Dit is hoe de Big Eight DBMS'en deze vragen behandelen:

  • Doe alsof er geen schakelaar was. Dit is wat de SQL-standaard lijkt te vereisen, hoewel het standaarddocument onduidelijk is:er staat alleen dat datums "worden beperkt door de natuurlijke regels voor datums die de Gregoriaanse kalender gebruiken" - wat voor "natuurlijke regels" ook zijn. Dit is de optie die DB2 heeft gekozen. Als er wordt beweerd dat de regels van een enkele kalender altijd van toepassing zijn geweest, zelfs op tijden dat niemand van de kalender had gehoord, is de technische term dat er een "proleptische" kalender van kracht is. We zouden bijvoorbeeld kunnen zeggen dat DB2 een proleptische Gregoriaanse kalender volgt.

  • Vermijd het probleem volledig. Microsoft en Sybase hebben hun minimale datumwaarden ingesteld op 1 januari 1753, ruim voorbij de tijd dat Amerika van kalender wisselde. Dit is verdedigbaar, maar van tijd tot tijd komen klachten naar voren dat deze twee DBMS'en een nuttige functionaliteit missen die de andere DBMS'en hebben en die de SQL-standaard vereist.

  • Kies 1582. Dit is wat Oracle deed. Een Oracle-gebruiker zou ontdekken dat de datum-rekenkundige uitdrukking 15 oktober 1582 minus 4 oktober 1582 een waarde van 1 dag oplevert (omdat 5-14 oktober niet bestaat) en dat de datum 29 februari 1300 geldig is (omdat de Juliaanse sprong- jaarregel van toepassing). Waarom deed Oracle extra moeite als de SQL-standaard dit niet lijkt te vereisen? Het antwoord is dat gebruikers het misschien nodig hebben. Historici en astronomen gebruiken dit hybride systeem in plaats van een proleptische Gregoriaanse kalender. (Dit is ook de standaardoptie die Sun heeft gekozen bij het implementeren van de GregorianCalendar-klasse voor Java - ondanks de naam is GregorianCalendar een hybride kalender.)

Dit bovenstaande citaat uit de volgende link:

Afstemming van SQL-prestaties:datums in SQL



  1. Afstemmen van invoer/uitvoer (I/O) bewerkingen voor PostgreSQL

  2. Voeg query toe met alleen kolommen die alle waarden in de `in`-clausule hebben

  3. Een Enum-veld wijzigen met Alembic

  4. Correcte manier om LIKE '%{$var}%' te gebruiken met voorbereide verklaringen? [mysqli]