patternsqlMinor
Stuffing a datetime value into a datetime2 column
Viewed 0 times
stuffingdatetime2columnintovaluedatetime
Problem
Today I saw the following statement in a code review:
The GETUTCDATE() function returns a
Does it have any significance that the two types are different? Would it be better to use SYSUTCDATETIME() to create a
ALTER TABLE dbo.MyTable ADD CreateDate DATETIME2(0) NOT NULL DEFAULT GETUTCDATE()The GETUTCDATE() function returns a
datetime and is then stuffed into a datetime2 column.Does it have any significance that the two types are different? Would it be better to use SYSUTCDATETIME() to create a
datetime2 value?Solution
Your column
Let's take your table definition and turn it into an example:
We then add some values to the table:
Let's see if there is a difference between
ID
CreateDate
CreateDateSYS
1
2023-03-30 07:21:12
2023-03-30 07:21:12
2
2023-03-30 07:21:12
2023-03-30 07:21:12
3
2023-03-30 07:16:45
2023-03-30 07:16:45
4
2023-03-30 07:16:45
2023-03-30 07:16:45
5
2023-03-30 07:16:45
2023-03-30 07:16:45
6
2023-03-30 07:16:45
2023-03-30 07:16:45
7
2023-03-30 07:16:45
2023-03-30 07:16:45
As you can see, inserting
If we create a table that has columns using
First we create the table:
Then we insert some datetime values with varying precision:
We then select the values from the table:
Which returns the following results:
ID
CreateDate
CreateDateSYS
1
2023-03-30 07:21:11.5500000
2023-03-30 07:21:11.5500000
2
2023-03-30 07:21:11.5508485
2023-03-30 07:21:11.5508485
3
2023-03-30 07:16:45.1000000
2023-03-30 07:16:45.1000000
4
2023-03-30 07:16:45.1200000
2023-03-30 07:16:45.1200000
5
2023-03-30 07:16:45.1230000
2023-03-30 07:16:45.1230000
6
2023-03-30 07:16:45.1234000
2023-03-30 07:16:45.1234000
7
2023-03-30 07:16:45.1234500
2023-03-30 07:16:45.1234500
Note:
The examples used in this answer can be run and tested over on db<>fiddle
Answering Your Questions
Does it have any significance that the two types are different?
In your case not, because you defined your column
Would it be better to use
In your case not, because even though you would be creating a
If your question were to encompass a possible performance impact when inserting data...
...then there can be a slight overhead, when certain values are passed to the column. This is due to an implicit conversion that occurs. This can be obtained from the execution plan.
-
When inserting dates into the
-
When inserting dates into the
-
You will not observe an implicit conversion when inserting
Following a screen shot of an execution plan containing the
Possible Solution
If you were to
If you don't require such a
CreateDate is using DATETIME2(0) for the date definition. Inserting either SYSUTCDATETIME() or GETUTCDATE() has no difference when retrieving the values from the table.Let's take your table definition and turn it into an example:
CREATE TABLE dbo.MyTable
(
ID int IDENTITY (1,1),
CreateDate DATETIME2(0) NOT NULL DEFAULT GETUTCDATE(),
CreateDateSYS DATETIME2(0) NOT NULL DEFAULT SYSUTCDATETIME()
);We then add some values to the table:
INSERT INTO MyTable (CreateDate, CreateDateSYS)
VALUES
(GETUTCDATE(),GETUTCDATE()),
(SYSUTCDATETIME(), SYSUTCDATETIME()),
('2023-03-30 07:16:45.1','2023-03-30 07:16:45.1'),
('2023-03-30 07:16:45.12','2023-03-30 07:16:45.12'),
('2023-03-30 07:16:45.123','2023-03-30 07:16:45.123'),
('2023-03-30 07:16:45.1234','2023-03-30 07:16:45.1234'),
('2023-03-30 07:16:45.12345','2023-03-30 07:16:45.12345')
;Let's see if there is a difference between
SYSUTCDATETIME() and GETUTCDATE():SELECT * FROM MyTable;ID
CreateDate
CreateDateSYS
1
2023-03-30 07:21:12
2023-03-30 07:21:12
2
2023-03-30 07:21:12
2023-03-30 07:21:12
3
2023-03-30 07:16:45
2023-03-30 07:16:45
4
2023-03-30 07:16:45
2023-03-30 07:16:45
5
2023-03-30 07:16:45
2023-03-30 07:16:45
6
2023-03-30 07:16:45
2023-03-30 07:16:45
7
2023-03-30 07:16:45
2023-03-30 07:16:45
As you can see, inserting
GETUTCDATE() or SYSUTCDATETIME() has no impact on what is stored. This is because the columns (as in your example) had been defined using DATETIME2(0) which is the default precision.If we create a table that has columns using
DATETIME2(7) (which is a higher precision) and insert different values, then we receive the following results.First we create the table:
CREATE TABLE dbo.MyTableFixed
(
ID int IDENTITY (1,1),
CreateDate DATETIME2(7) NOT NULL DEFAULT GETUTCDATE(),
CreateDateSYS DATETIME2(7) NOT NULL DEFAULT SYSUTCDATETIME()
);Then we insert some datetime values with varying precision:
INSERT INTO MyTableFixed (CreateDate, CreateDateSYS)
VALUES
(GETUTCDATE(),GETUTCDATE()),
(SYSUTCDATETIME(), SYSUTCDATETIME()),
('2023-03-30 07:16:45.1','2023-03-30 07:16:45.1'),
('2023-03-30 07:16:45.12','2023-03-30 07:16:45.12'),
('2023-03-30 07:16:45.123','2023-03-30 07:16:45.123'),
('2023-03-30 07:16:45.1234','2023-03-30 07:16:45.1234'),
('2023-03-30 07:16:45.12345','2023-03-30 07:16:45.12345')
;We then select the values from the table:
SELECT * FROM MyTableFixed;Which returns the following results:
ID
CreateDate
CreateDateSYS
1
2023-03-30 07:21:11.5500000
2023-03-30 07:21:11.5500000
2
2023-03-30 07:21:11.5508485
2023-03-30 07:21:11.5508485
3
2023-03-30 07:16:45.1000000
2023-03-30 07:16:45.1000000
4
2023-03-30 07:16:45.1200000
2023-03-30 07:16:45.1200000
5
2023-03-30 07:16:45.1230000
2023-03-30 07:16:45.1230000
6
2023-03-30 07:16:45.1234000
2023-03-30 07:16:45.1234000
7
2023-03-30 07:16:45.1234500
2023-03-30 07:16:45.1234500
Note:
The examples used in this answer can be run and tested over on db<>fiddle
Answering Your Questions
Does it have any significance that the two types are different?
In your case not, because you defined your column
CreateDate with a low precision DATETIME2(0) type.Would it be better to use
SYSUTCDATETIME() to create a datetime2 value?In your case not, because even though you would be creating a
DATETIME2 value with a high precision, you are storing it in a DATETIME2(0) column which has a lower precision.If your question were to encompass a possible performance impact when inserting data...
...then there can be a slight overhead, when certain values are passed to the column. This is due to an implicit conversion that occurs. This can be obtained from the execution plan.
-
When inserting dates into the
DATETIME2(0) defined column you may observeCONVERT_IMPLICIT(datetime2(0),[@1],0) -- actual value
CONVERT_IMPLICIT(datetime2(0),getutcdate(),0) -- getutcdate()
CONVERT_IMPLICIT(datetime2(0),sysutcdatetime(),0) -- sysutcdatetime()-
When inserting dates into the
DATETIME2(7) defined column you may observeCONVERT_IMPLICIT(datetime2(7),[@1],0) -- actual value
CONVERT_IMPLICIT(datetime2(7),getutcdate(),0) -- getutcdate()-
You will not observe an implicit conversion when inserting
sysutcdatetime() into the DATETIME2(7) defined column. This is because the values does not have to be converted from one datetime format to another. SYSUTCDATETIME() will return a true DATETIME2(7) formatted value.Scalar Operator(sysutcdatetime()) -- sysutcdatetime()Following a screen shot of an execution plan containing the
CONVERT_IMPLICIT conversion:Possible Solution
If you were to
ALTER your column to use DATETIME2(7) which stores a higher precision DATETIME2 value, then you could benefit from switching to SYSUTCDATETIME().If you don't require such a
Code Snippets
CREATE TABLE dbo.MyTable
(
ID int IDENTITY (1,1),
CreateDate DATETIME2(0) NOT NULL DEFAULT GETUTCDATE(),
CreateDateSYS DATETIME2(0) NOT NULL DEFAULT SYSUTCDATETIME()
);INSERT INTO MyTable (CreateDate, CreateDateSYS)
VALUES
(GETUTCDATE(),GETUTCDATE()),
(SYSUTCDATETIME(), SYSUTCDATETIME()),
('2023-03-30 07:16:45.1','2023-03-30 07:16:45.1'),
('2023-03-30 07:16:45.12','2023-03-30 07:16:45.12'),
('2023-03-30 07:16:45.123','2023-03-30 07:16:45.123'),
('2023-03-30 07:16:45.1234','2023-03-30 07:16:45.1234'),
('2023-03-30 07:16:45.12345','2023-03-30 07:16:45.12345')
;SELECT * FROM MyTable;CREATE TABLE dbo.MyTableFixed
(
ID int IDENTITY (1,1),
CreateDate DATETIME2(7) NOT NULL DEFAULT GETUTCDATE(),
CreateDateSYS DATETIME2(7) NOT NULL DEFAULT SYSUTCDATETIME()
);INSERT INTO MyTableFixed (CreateDate, CreateDateSYS)
VALUES
(GETUTCDATE(),GETUTCDATE()),
(SYSUTCDATETIME(), SYSUTCDATETIME()),
('2023-03-30 07:16:45.1','2023-03-30 07:16:45.1'),
('2023-03-30 07:16:45.12','2023-03-30 07:16:45.12'),
('2023-03-30 07:16:45.123','2023-03-30 07:16:45.123'),
('2023-03-30 07:16:45.1234','2023-03-30 07:16:45.1234'),
('2023-03-30 07:16:45.12345','2023-03-30 07:16:45.12345')
;Context
StackExchange Database Administrators Q#325365, answer score: 6
Revisions (0)
No revisions yet.