Which one:
is the recommended way to store date and time in SQL Server 2008+?
I\'m aware of differ
Select ValidUntil + 1
from Documents
The above SQL won't work with a DateTime2 field. It returns and error "Operand type clash: datetime2 is incompatible with int"
Adding 1 to get the next day is something developers have been doing with dates for years. Now Microsoft have a super new datetime2 field that cannot handle this simple functionality.
"Let's use this new type that is worse than the old one", I don't think so!
Interpretation of date strings into datetime
and datetime2
can be different too, when using non-US DATEFORMAT
settings. E.g.
set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2
This returns 2013-05-06
(i.e. May 6) for datetime
, and 2013-06-05
(i.e. June 5) for datetime2
. However, with dateformat
set to mdy
, both @d
and @d2
return 2013-06-05
.
The datetime
behavior seems at odds with the MSDN documentation of SET DATEFORMAT
which states: Some character strings formats, for example ISO 8601, are interpreted independently of the DATEFORMAT setting. Obviously not true!
Until I was bitten by this, I'd always thought that yyyy-mm-dd
dates would just be handled right, regardless of the language / locale settings.
I concurr with @marc_s and @Adam_Poward -- DateTime2 is the preferred method moving forward. It has a wider range of dates, higher precision, and uses equal or less storage (depending on precision).
One thing the discussion missed, however...
@Marc_s states: Both types map to System.DateTime in .NET - no difference there
. This is correct, however, the inverse is not true...and it matters when doing date range searches (e.g. "find me all records modified on 5/5/2010").
.NET's version of Datetime
has similar range and precision to DateTime2
. When mapping a .net Datetime
down to the old SQL DateTime
an implicit rounding occurs. The old SQL DateTime
is accurate to 3 milliseconds. This means that 11:59:59.997
is as close as you can get to the end of the day. Anything higher is rounded up to the following day.
Try this :
declare @d1 datetime = '5/5/2010 23:59:59.999'
declare @d2 datetime2 = '5/5/2010 23:59:59.999'
declare @d3 datetime = '5/5/2010 23:59:59.997'
select @d1 as 'IAmMay6BecauseOfRounding', @d2 'May5', @d3 'StillMay5Because2msEarlier'
Avoiding this implicit rounding is a significant reason to move to DateTime2. Implicit rounding of dates clearly causes confusion:
datetime2 wins in most aspects except (old apps Compatibility)
please note the following points
image source : MCTS Self-Paced Training Kit (Exam 70-432): Microsoft® SQL Server® 2008 - Implementation and Maintenance Chapter 3:Tables -> Lesson 1: Creating Tables -> page 66
DateTime2 wreaks havoc if you are an Access developer trying to write Now() to the field in question. Just did an Access -> SQL 2008 R2 migration and it put all the datetime fields in as DateTime2. Appending a record with Now() as the value bombed out. It was okay on 1/1/2012 2:53:04 PM, but not on 1/10/2012 2:53:04 PM.
Once character made the difference. Hope it helps somebody.
Here is an example that will show you the differences in storage size (bytes) and precision between smalldatetime, datetime, datetime2(0), and datetime2(7):
DECLARE @temp TABLE (
sdt smalldatetime,
dt datetime,
dt20 datetime2(0),
dt27 datetime2(7)
)
INSERT @temp
SELECT getdate(),getdate(),getdate(),getdate()
SELECT sdt,DATALENGTH(sdt) as sdt_bytes,
dt,DATALENGTH(dt) as dt_bytes,
dt20,DATALENGTH(dt20) as dt20_bytes,
dt27, DATALENGTH(dt27) as dt27_bytes FROM @temp
which returns
sdt sdt_bytes dt dt_bytes dt20 dt20_bytes dt27 dt27_bytes
------------------- --------- ----------------------- -------- ------------------- ---------- --------------------------- ----------
2015-09-11 11:26:00 4 2015-09-11 11:25:42.417 8 2015-09-11 11:25:42 6 2015-09-11 11:25:42.4170000 8
So if I want to store information down to the second - but not to the millisecond - I can save 2 bytes each if I use datetime2(0) instead of datetime or datetime2(7).