Który:
jest zalecany sposób, aby data i czas przechowywania w SQL Server 2008+?
Zdaję sobie sprawę z różnic w precyzji (i prawdopodobnie przestrzeni dyskowej), ale na razie je ignorując, czy istnieje dokument z najlepszymi praktykami określający, kiedy użyć, a może powinniśmy używać datetime2
tylko?
DateTime2
typu (lub dowolnego innego programu SQL Server Wpisz tę sprawę)? Zobacz wady w mojej odpowiedzi z 7/10/17 poniżej, dlaczego pytamDATETIME2
ma zakres dat od „DATETIME
0001/01/01 ” do „ 9999/12/31 ”, podczas gdy typ obsługuje tylko lata 1753-9999.Ponadto, jeśli potrzebujesz,
DATETIME2
możesz być bardziej precyzyjny pod względem czasu; DATETIME jest ograniczony do 3 1/3 milisekund, aDATETIME2
może być dokładny do 100ns.Oba typy mapują na
System.DateTime
.NET - nie ma różnicy.Jeśli masz wybór, zalecałbym używanie,
DATETIME2
gdy tylko jest to możliwe. Nie widzę żadnych korzyściDATETIME
(z wyjątkiem kompatybilności wstecznej) - będziesz miał mniej problemów (daty są poza zakresem i takie kłopoty).Plus: jeśli potrzebujesz tylko daty (bez części czasu), użyj DATE - jest tak samo dobra, jak
DATETIME2
i oszczędza miejsce! :-) To samo dotyczy tylko czasu - użyjTIME
. Po to są te typy!źródło
Nullable<DateTime>
jest?datetime2 wygrywa w większości aspektów z wyjątkiem (kompatybilności ze starymi aplikacjami)
proszę zwrócić uwagę na następujące punkty
źródło obrazu: Zestaw szkoleniowy MCTS (egzamin 70-432): Microsoft® SQL Server® 2008 - Implementacja i konserwacja Rozdział 3: Tabele -> Lekcja 1: Tworzenie tabel -> strona 66
źródło
datetime2
są niesamowite (Zwycięzca)datetime2
wykorzystuje mniej miejsca do przechowywania,datetime
a jednocześnie oferuje większy zasięg i większą precyzję?Zgadzam się z @marc_s i @Adam_Poward - DateTime2 jest preferowaną metodą przechodzenia do przodu. Ma szerszy zakres dat, wyższą precyzję i zużywa mniej więcej tyle samo miejsca (w zależności od precyzji).
Jedną rzeczą dyskusja brakowało jednak ...
@Marc_s stwierdza:
Both types map to System.DateTime in .NET - no difference there
. Jest to poprawne, jednak odwrotność nie jest prawdziwa ... i ma to znaczenie przy wyszukiwaniu zakresu dat (np. „Znajdź wszystkie rekordy zmodyfikowane 05.05.2010”).Wersja .NET
Datetime
ma podobny zasięg i precyzję doDateTime2
. Podczas mapowania .net wDatetime
dół do starego SQLDateTime
występuje niejawne zaokrąglenie . Stary SQLDateTime
ma dokładność do 3 milisekund. Oznacza to, że11:59:59.997
jest tak blisko, jak to możliwe, do końca dnia. Wszystko wyższe jest zaokrąglane do następnego dnia.Spróbuj tego :
Unikanie tego niejawnego zaokrąglania jest istotnym powodem przejścia na DateTime2. Domniemane zaokrąglanie dat wyraźnie powoduje zamieszanie:
źródło
20100505
na5/5/2010
? Poprzedni format będzie działał z dowolnym regionem w SQL Server. Ten ostatni się załamie:SET LANGUAGE French; SELECT Convert(datetime, '1/7/2015')
ups:2015-07-01 00:00:00.000
Prawie wszystkie odpowiedzi i komentarze były bardzo mocne dla zalet i lekkie dla wad. Oto podsumowanie wszystkich dotychczasowych zalet i wad oraz niektóre kluczowe wady (w punkcie 2 poniżej), o których widziałem tylko raz lub wcale.
1.1 Bardziej zgodny z ISO (ISO 8601) (choć nie wiem, jak to się dzieje w praktyce).
1.2 Większy zakres (1/1/0001 do 12/31/9999 vs. 1/1 / 1753-12 / 31/9999) (chociaż dodatkowy zakres, wszystkie przed rokiem 1753, prawdopodobnie nie będzie stosowany, z wyjątkiem np. w aplikacjach historycznych, astronomicznych, geologicznych itp.).
1.3 Dokładnie pasuje do zakresu zakresu typu .NET
DateTime
(chociaż oba konwertują tam iz powrotem bez specjalnego kodowania, jeśli wartości mieszczą się w zakresie i precyzji typu docelowego, z wyjątkiem Con # 2.1 poniżej, w przeciwnym razie wystąpi błąd / zaokrąglenie).1.4 Większa precyzja (100 nanosekund, czyli 0,000,000,1 sek. Vs. 3,33 milisekunda, czyli 0,003,33 sek.) (Chociaż dodatkowa precyzja prawdopodobnie nie zostanie wykorzystana, z wyjątkiem np. Aplikacji inżynierskich / naukowych).
1.5 Po skonfigurowaniu dla podobnej (jak w 1 milisek nie „takiej samej” (jak w 3,33 milisek), jak twierdzi Iman Abidi) precyzji, ponieważ
DateTime
zużywa mniej miejsca (7 vs 8 bajtów), ale wtedy oczywiście straciłbyś precyzja korzyści, która prawdopodobnie jest jedną z dwóch (druga to zakres) najbardziej reklamowana, choć prawdopodobnie niepotrzebnymi korzyściami).2.1 Podczas przekazywania parametru do .NET
SqlCommand
, musisz określić,System.Data.SqlDbType.DateTime2
czy możesz przekazać wartość pozaDateTime
zakresem i / lub precyzją SQL Servera , ponieważ domyślnie jest toSystem.Data.SqlDbType.DateTime
.2.2 Nie można go niejawnie / łatwo przekonwertować na zmiennoprzecinkową wartość liczbową (liczbę dni od minimalnej daty i godziny), aby wykonać następujące czynności w wyrażeniach programu SQL Server za pomocą wartości liczbowych i operatorów:
2.2.1 dodaj lub odejmij # dni lub częściowe dni. Uwaga: użycie
DateAdd
funkcji jako obejścia nie jest trywialne, gdy trzeba rozważyć wiele, jeśli nie wszystkie części daty i godziny.2.2.2 weź pod uwagę różnicę między dwiema datami dla celów obliczenia „wieku”. Uwaga: Zamiast tego nie można po prostu użyć
DateDiff
funkcji programu SQL Server , ponieważ nie oblicza się,age
jak większość ludzi by się spodziewała, gdyby dwie daty i godziny przekroczyły granicę daty / godziny kalendarza / zegara jednostek określonych, nawet jeśli to tylko ułamek tej jednostki, zwróci różnicę jako 1 tej jednostki w stosunku do 0. Na przykład,DateDiff
wDay
dwóch datach tylko 1 milisekunda od siebie zwróci 1 w stosunku do 0 (dni), jeśli te daty są w różne dni kalendarzowe (tj. „1999-12-31 23: 59: 59.9999999” i „2000-01-01 00: 00: 00.0000000”). Ta sama różnica 1 milisekundy data-godzina, jeśli zostanie przeniesiona tak, aby nie przekraczała dnia kalendarzowego, zwróci „DateDiff” wDay
wartości 0 (dni).2.2.3 weź
Avg
pod uwagę daty i godziny (w zapytaniu zbiorczym), po prostu konwertując najpierw na „Float”, a następnie ponownie naDateTime
.UWAGA: Aby przekonwertować
DateTime2
na wartość liczbową, musisz zrobić coś w rodzaju następującej formuły, która nadal zakłada, że twoje wartości nie są mniejsze niż w roku 1970 (co oznacza, że tracisz cały dodatkowy zakres plus kolejne 217 lat. Uwaga: Możesz nie można po prostu dostosować formuły, aby umożliwić dodatkowy zasięg, ponieważ możesz napotkać problemy z przepełnieniem numerycznym.25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0
- Źródło: „ https://siderite.dev/blog/how-to-translate-t-sql-datetime2-to.html ”Oczywiście, można też
Cast
naDateTime
pierwszy (i ewentualnie z powrotem doDateTime2
), ale trzeba by stracić dokładność i zasięg (wszystkie poprzedzające rok 1753) Korzyści zDateTime2
vs.DateTime
które są naprawde 2 największe i również w tym samym czasie prolly 2 najmniej prawdopodobne potrzeby, które nasuwają pytanie, po co z niego korzystać, gdy tracisz niejawną / łatwą konwersję na zmiennoprzecinkową liczbę (liczbę dni) w celu dodania / odjęcia / korzyści związanych z wiekiem (vs.DateDiff
) /Avg
cieląt, która jest duża z mojego doświadczenia.Przy okazji,
Avg
data jest ważnym (lub przynajmniej powinna być) ważnym przypadkiem użycia. a) Oprócz użycia w uzyskiwaniu średniego czasu trwania, gdy daty i godziny (od wspólnej podstawowej daty i godziny) są używane do reprezentowania czasu trwania (powszechna praktyka), b) przydatne jest również uzyskanie statystyki typu deski rozdzielczej na temat średniej daty czas znajduje się w kolumnie daty i godziny zakresu / grupy wierszy. c) Standardowe (lub przynajmniej powinno być standardowe) zapytanie ad-hoc do monitorowania / rozwiązywania problemów z wartościami w kolumnie, które mogą nie być ważne / już dłużej i / lub mogą wymagać wycofania, to podać dla każdej wartości liczbę wystąpień oraz (jeśli są dostępne), żeMin
,Avg
iMax
znaczków data-czas związany z tą wartością.źródło
DateTime
, są związane z wpływem na zapytania i instrukcje SQL Server.DateTime2
już wspomniane (ze względu na duże ryzyko przepełnienia)). Re. „nie działa w przypadku większości typów dat”: potrzebujesz go tylko do pracy z jednym, a większość dat w większości aplikacji prawdopodobnie nigdy nie będzie musiała być konwertowana na inny typ daty przez cały okres ich użytkowania (z wyjątkiem może, jak wspomniałem, również ,DateTime2
abyDateTime
(np. wykonać „arytmetykę w datach”; P). Biorąc to pod uwagę, nie jest warte całego dodatkowego kodowania w nie tylko zaprogramowanych, ale również doraźnych zapytaniach badawczych, aby użyć nie-arytmetycznego typu daty.DateTime2 sieje spustoszenie, jeśli jesteś programistą Access, który próbuje napisać Now () w odpowiednim polu. Właśnie wykonałem migrację Access -> SQL 2008 R2 i umieściłem wszystkie pola daty i godziny jako DateTime2. Dołączanie rekordu za pomocą Now () jako wartości zbombardowanej. W dniu 01.01.2012 14:53:04 było w porządku, ale nie w dniu 01.10.2012 14:53:04 PM.
Kiedyś postać zrobiła różnicę. Mam nadzieję, że to komuś pomoże.
źródło
Oto przykład, który pokaże różnice w wielkości pamięci (bajtach) i precyzji między smalldatetime, datetime, datetime2 (0) i datetime2 (7):
który zwraca
Więc jeśli chcę przechowywać informacje do drugiej - ale nie do milisekundy - mogę zapisać 2 bajty każdy, jeśli użyję datetime2 (0) zamiast datetime lub datetime2 (7).
źródło
podczas gdy zwiększa się precyzja w datetime2 , niektórzy klienci nie obsługują daty , godziny ani datetime2 i zmuszają cię do konwersji na literał łańcuchowy. W szczególności Microsoft wspomina o problemach ODBC, OLE DB, JDBC i SqlClient „niższego poziomu” z tymi typami danych i ma wykres pokazujący, w jaki sposób każdy może odwzorować typ.
Jeśli cenisz zgodność zamiast precyzji, użyj datetime
źródło
Stare pytanie ... Ale chcę dodać coś, co nie zostało tu jeszcze powiedziane ... (Uwaga: To moja własna obserwacja, więc nie pytaj o żadne odniesienia)
Datetime2 jest szybszy, gdy jest używany w kryteriach filtrowania.
TLDR:
W SQL 2016 miałem tabelę ze sto tysiącami wierszy i kolumnę daty i godziny ENTRY_TIME, ponieważ wymagane było przechowywanie dokładnego czasu do sekund. Podczas wykonywania złożonego zapytania z wieloma złączeniami i podpytaniem, gdy użyłem klauzuli where jako:
Zapytanie początkowo działało poprawnie, gdy były setki wierszy, ale gdy liczba wierszy wzrosła, zapytanie zaczęło dawać ten błąd:
Usunąłem klauzulę where i nieoczekiwanie zapytanie zostało uruchomione w ciągu 1 sekundy, chociaż teraz WSZYSTKIE wiersze dla wszystkich dat zostały pobrane. Uruchamiam wewnętrzne zapytanie z klauzulą where i zajęło 85 sekund, a bez klauzuli zabrało 0,01 sekundy.
Spotkałem się tutaj z wieloma wątkami dotyczącymi tego problemu jako wydajności filtrowania według czasu i daty
Zoptymalizowałem trochę zapytanie. Ale prawdziwą prędkością, jaką uzyskałem, była zmiana kolumny datetime na datetime2.
Teraz to samo zapytanie, które przekroczyło limit czasu, zajmuje mniej niż sekundę.
Twoje zdrowie
źródło
Interpretacja ciągów daty na
datetime
idatetime2
może być również inna, gdy używane sąDATEFORMAT
ustawienia spoza USA . Na przykładZwraca
2013-05-06
(tj. 6 maja) dladatetime
i2013-06-05
(tj. 5 czerwca) dladatetime2
. Jednak zdateformat
ustawionym namdy
oba@d
i@d2
wróć2013-06-05
.datetime
Zachowanie wydaje się sprzeczne z dokumentacji MSDN zSET DATEFORMAT
których stwierdza: Niektóre formaty ciągów znaków, na przykład ISO 8601, są interpretowane niezależnie od ustawienia dateformat . Oczywiście nieprawda!Dopóki mnie to nie ugryzło, zawsze myślałem, że
yyyy-mm-dd
daty będą obsługiwane właściwie, niezależnie od ustawień języka / ustawień regionalnych.źródło
SET LANGUAGE FRENCH; DECLARE @d DATETIME = '20130605'; SELECT @d;
Spróbuj ponownie z myślnikami.Zgodnie z tym artykułem , jeśli chcesz mieć tę samą precyzję DateTime przy użyciu DateTime2, po prostu musisz użyć DateTime2 (3). To powinno dać ci taką samą precyzję, zająć o jeden mniej bajtów i zapewnić rozszerzony zakres.
źródło
Właśnie natknąłem się na jeszcze jedną zaletę
DATETIME2
: pozwala uniknąć błędu wadodbapi
module Pythona , który wybuchnie, jeślidatetime
zostanie przekazana standardowa wartość biblioteki, która ma niezerowe mikrosekundy dlaDATETIME
kolumny, ale działa dobrze, jeśli kolumna jest zdefiniowana jakoDATETIME2
.źródło
Powyższy kod SQL nie będzie działać z polem DateTime2. Zwraca błąd „Zderzenie typu argumentu: datetime2 jest niezgodny z int”
Dodanie 1, aby uzyskać następny dzień, jest czymś, co programiści robią z datami od lat. Teraz Microsoft ma super nowe pole datetime2, które nie obsługuje tej prostej funkcji.
„Użyjmy tego nowego typu, który jest gorszy od starego”, nie sądzę!
źródło
datetime
idatetime2
typy danych zostały wprowadzone zarówno w SQL Server 2008 można również uzyskaćOperand type clash: date is incompatible with int
oddate
typu, który istnieje od dnia kropką.dateadd(dd, 1, ...)
Jednak wszystkie trzy typy danych działają dobrze .Myślę, że
DATETIME2
to lepszy sposób na przechowywaniedate
, ponieważ ma większą wydajność niżDATETIME
. WSQL Server 2008
można użyćDATETIME2
, przechowuje datę i godzinę, trwa 6-8bytes
do przechowywania i ma precyzję100 nanoseconds
. Każdy, kto potrzebuje większej precyzji czasu, będzie chciałDATETIME2
.źródło