I'm having a strange issue with the smalldatetime data type in SQL Server.
I have a very basic table
create table datetest (
value smalldatetime not null
)
And when I run the following
insert into datetest
values ('2016-12-29 21:30:00');
I see the value is 2016-12-29 21:30:00
Then when I run the following
update datetest
set value = '2016-12-29 21:31:30'
I see the value is 2016-12-29 21:31:00
It did not include the seconds. Why is this?
This is happening because precision of smalldatetime is 1 minute. It discards any seconds in datetime value by rounding off. For e.g:
'2014-10-10 12:13:29' is rounded off to '2014-10-10 12:13:00' and '2014-10-10 12:13:30' is rounded off to '2014-10-10 12:14:00'
This is one of the characteristics of smalldatetime over datetime.
Microsoft documentation on smalldatetime
The main differentation is that it rounds to the nearest minute. If you want to see seconds (and milliseconds) then you need to consider the datetime data type.
In your example however, it should return the value 2016-12-29 21:32:00 because it rounds up from 30 seconds to the next minute. anything less than 30 seconds gets rounded down. Example;
CREATE TABLE #DateTest (ID int, DateValue smalldatetime)
INSERT INTO #DateTest (ID, DateValue)
VALUES
(1,'2016-12-29 21:31:29')
,(2,'2016-12-29 21:31:30')
SELECT * FROM #DateTest
Output
ID DateValue
1 2016-12-29 21:31:00
2 2016-12-29 21:32:00
Some further reading links;
http://blog.sqlauthority.com/2010/06/01/sql-server-precision-of-smalldatetime-a-1-minute-precision/
http://sqlcoach.blogspot.co.uk/2007/08/sql-server-storing-time-coming-soon.html
http://sqlhints.com/2016/10/10/difference-between-smalldatetime-and-datetime-data-types-in-sql-server/
When the conversion is to datetime, the smalldatetime value is copied to the datetime value. The fractional seconds will make next nearest minutes. The following code shows the results of converting a smalldatetime value to a datetime value.
DECLARE #smalldatetime smalldatetime = '1955-12-13 12:43:10';
DECLARE #datetime datetime = #smalldatetime;
SELECT #smalldatetime AS '#smalldatetime', #datetime AS 'datetime';
--Result
--#smalldatetime datetime
------------------------- -----------------------
--1955-12-13 12:43:00 1955-12-13 12:43:00.000
Take a look MSDN Link
It rounds all seconds to minutes:
Time range:
00:00:00 through 23:59:59
2007-05-09 23:59:59 will round to
2007-05-10 00:00:00
see chapter smalldatetime Description: https://msdn.microsoft.com/en-us/library/ms182418(v=sql.120).aspx
Related
I'm inserting sample call data to the table ContactCallDetail. when I query the data inserted I'm getting datetime in the format yy-mm-dd hh-mm-ss-ff
declare #StartDateTime datetime = convert(varchar, getdate(), 20);
declare #EndDateTime datetime = dateadd(ss,20,#StartDateTime);
INSERT INTO ContactCallDetail values(0,NULL,'+xxxxx545xx77',#StartDateTime,#EndDateTime,0);
GO
select * from ContactCallDetail
SessionID SessionSeqNum originatorID CallingDN StartDateTime EndDateTime Transfer
100000 0 NULL +xxxxx5453xx7 2022-02-28 20:11:34.000 2022-02-28 20:11:54.000 0
I need to store the datetime without fractions part(ff). how can I achieve that? i want to see 2022-02-28 20:11:34 instead of 2022-02-28 20:11:34.000
The datetime data type always stores fractional seconds with a 1/300 second precision. Use datetime2(0) if you don't need fractional seconds. This will also save storage space (2 bytes).
Just to be sure and to add to #DanGuzman 's answer, you need to change the datatype of the StartDateTime and EndDateTime columns in the ContactCallDetail table to datetime2(0).
That will also make it so you don't have to do CONVERT either on the way in or the way out.
I'm trying to get the datetime of an event from n SQL-server and use the date to look up data in another table.
When I select the datetime variable from the 1st table it shows as...
2017-01-01 20:41:23.000
Data is parsed into a temporary table declared via
CREATE TABLE #RunData1
(
[MyDateTime] Datetime,
[Tag] nvarchar(50),
[Hours] float,
[id] INT IDENTITY(1,1),
[searched] bit
)
I store this value in a Datetime variable #startPoint (DECLARE #startPoint dateTime) and set it using SELECT #startPoint = MyDateTime FROM #RunData1 WHERE id = #currentid_inner
But when I then try and print #startpoint it shows as Jan 1 2017 8:41PM?
I thought at first this just might be some formatting in the print command. But when I try and subtract 10 seconds from this (SET #startpoint = DateAdd(SS,-10,#startPoint)) and use it to find data after this new time. I get data from after 2017-01-01 20:41:00.000 not 2017-01-01 20:41:13.000 (data sample time is 0.5 s)
Why is the date format changing from 2017-01-01 20:41:23.000 to Jan 1 2017 8:41PM causing me to lose seconds?
You are not losing seconds - this is just how the date is being displayed.
When it comes to displaying datetime values - let the application deal with that - not the database.
I have a logs table with a smalldatetime column.
When I'm inserting into the table the value of GETDATE() the data is inserted without the seconds.
Example result: 2017-01-15 15:20:00
What am I missing?
From MSDN
smalldatetime
Defines a date that is combined with a time of day. The time is based
on a 24-hour day, with seconds always zero (:00) and without
fractional seconds.
If you want seconds then use DATETIME datatype instead of smalldatetime
DECLARE #smalldatetime SMALLDATETIME = '1955-12-13 12:43:10',
#datetime DATETIME = '1955-12-13 12:43:10'
SELECT #smalldatetime as [SmallDateTime],
#datetime as [DateTime]
Result :
+---------------------+-------------------------+
| SmallDateTime | DateTime |
+---------------------+-------------------------+
| 1955-12-13 12:43:00 | 1955-12-13 12:43:10.000 |
+---------------------+-------------------------+
For Sql Server 2008 and above:
Use datetime2(p) instead of smalldatetime and sysdatetime() instead of getdate().
datetime is 8 bytes; 1753-01-01T00:00:00.000 to 9999-12-31T23:59:59.997 (time rounded to .000, .003, .007)
datetime2(2) is 6 bytes; 0001-01-01T00:00:00.00 to 9999-12-31T23:59:59.99
datetime2(4) is 7 bytes; 0001-01-01T00:00:00.0000 to 9999-12-31T23:59:59.9999
datetime2(7) is 8 bytes; 0001-01-01T00:00:00.0000000 to 9999-12-31T23:59:59.9999999
Note: When adding a .NET DateTime as a parameter, use System.Data.SqlDbType.DateTime2. datetime2 can store any value that can be stored in the .NET DateTime type.
Learn more:
sql-server-datetime2-vs-datetime
datetime (Transact-SQL)
datetime2 (Transact-SQL)
In SQL Server 2005 I am interrogating some old legacy data and I need to combine the date component of a datetime column with the time component from another column. Here's an example:
DateColumn: 2016-05-09 00:00:00.000
TimeColumn: 1899-12-30 12:26:00.000
I need the end result converted to the following DateTime:
ResultDateTime: 2016-05-09 12:26:00.000
I tried using:
CAST(DateColumn AS DATETIME) + CAST(TimeColumn AS TIME) AS ResultDateTime
But SQL Server 2005 doesn't recognize the type TIME.
Can someone please show me a way of doing that?
Many thanks!
convert the time column to string HH:MM:SS and add to the date column
ResultDatetIme = DateColumn + convert(varchar(10), TimeColumn, 108)
You can just use DATEADD and DATEDIFF, assuming that the time column's date portion is always 30/12/1899:
declare #t table (DateColumn datetime,TimeColumn datetime)
insert into #t(DateColumn,TimeColumn) values
('2016-05-09T00:00:00.000','1899-12-30T12:26:00.000')
select DATEADD(millisecond,DATEDIFF(millisecond,'18991230',TimeColumn),DateColumn)
from #t
Result:
-----------------------
2016-05-09 12:26:00.000
As you can see following data type supported in SQL 2005:
https://msdn.microsoft.com/en-us/library/ms187819(v=sql.90).aspx
Use datetime and smalldatetime, The smalldatetime data type stores dates and times of day with less precision than datetime. The Database Engine stores smalldatetime values as two 2-byte integers. The first 2 bytes store the number of days after January 1, 1900. The other 2 bytes store the number of minutes since midnight.
datetime values are rounded to increments of .000, .003, or .007 seconds, as shown in the following table.
SELECT CAST('2016-05-09 00:00:00.000' AS DATETIME) + CAST('1900-01-01 12:26:00.000' AS smalldatetime) AS ResultDateTime
Result: 2016-05-09 12:26:00.000
So you can use datetime and smalldatetime, hope fully that will work for you.
Let me know if any issue. love to resolve :)
I'm working with a db (SQL server 2008), and have an interesting issue with times stored in the db.
The DBA who originally set it up was crafty and stored scheduled times as smallints in 12-hour form-- 6:00AM would be represented as 600. I've figured out how to split them into hours and minutes like thus:
select floor(time/100) as hr, right(time, 2) as min from table;
What I want to do is compare these scheduled times to actual times, which are stored in the proper datetime format. Ideally, I would do this with two datetime fields and use datediff() between them, but this would require converting the smallint time into a datetime, which I can't figure out.
Does anyone have suggestions on how to do this?
Thanks in advance.
Can think of two ways to do that. The first is to build a string in the HH:MM format, and cast that to datetime. The second is to convert the smallint format to float with the number of days as unit. The number of days is the internal time representation, so you can cast that to datetime too.
Example code:
declare #i smallint
set #i = 621
-- Cast to a string '6:21', then to a datetime
select cast(CAST(#i / 100 as varchar) + ':' + CAST(#i % 100 as varchar)
as datetime)
-- Convert to number of days, which is the interal datetime format
select cast((#i/100)/24.0 + (#i%100)/(24*60.0) as datetime)
P.S. If you divide an integer by another integer. the result is a third integer: 100 / 24 = 4. If you divide an integer by a float, the result is a float: 100 / 24.0 = 4.16666.
Since you are using SQL Server 2008, you can take advantage of the new Time data type. In order to convert the integer to a time value, we need to assume that the last two digits are minutes. To get the minute portion, divide by 100, take the integer portion and subtract it from the initial value. So in the case of 621 we get:
621 - Floor(621/100)* 100
621 - Floor(6.21)*100
621 - 6*100
621 - 600 = 21 minutes
For the hour portion, we can simply take the integer value after dividing by 100.
Create Table #Test( IntVal smallint not null )
Insert #Test Values( 621 )
Insert #Test Values( 2359 )
Insert #Test Values( 1200 )
Insert #Test Values( 1201 )
Insert #Test Values( 1159 )
Select Z.TimeVal, GetDate(), DateDiff(hh, Z.TimeVal, Cast(GetDate() As Time(0)))
From (
Select Cast(DateAdd(mi
, IntVal - Floor(IntVal/100)*100
, DateAdd(hh, Floor(IntVal/100), 0)
) As Time(0)) As TimeVal
From #Test
) As Z
Part of the trick here is to use DateAdd(hh, Floor(IntVal/100), 0) which does a DateAdd against the zero value for datetime.