Convert numeric(32,0) to DATETIME in SSIS job - sql-server

My data source is giving me a column of type numeric(32,0) that is the epoch value, and I want to convert that to a DATETIME in my database. I've got a Derived Column transform and for the expression I tried to do this:
DATEADD("SECOND", CAST([Last Modified Date] AS BIGINT) / 1000, (DT_DBTIMESTAMP)"1970-01-01")
But it's giving me parsing errors. Can someone help me with the proper syntax for this please? If I don't quote "SECOND" then it immediately tells me that SECOND is not an input column.
Even though the input is the numeric(32,0) type they're all integer values, such as 1564371486110.

I do not immediately understand your cast and divide by 1000.
SSMS
select datediff(ss, '1970-01-01 00:00:00', getdate())
1564069434
Expression
dateadd("SS", 1564069434, (DT_DBTIMESTAMP)"1970-01-01 00:00:00")
2019-07-25 15:51:17.763
Edit - I am going to assume you're dividing for milliseconds on the epoch time.
Derived Column Transformation Editor - Expression
DATEADD("SS",(DT_UI8)SUBSTRING((DT_WSTR,32)epochtime,1,LEN(TRIM((DT_WSTR,32)epochtime)) - 3),(DT_DBTIMESTAMP)"1970-01-01 00:00:00")

Related

T SQL Conversion failed when converting date and/or time from character string from VARCHAR(MAX)

I'm using SQL Server 2014. I have a date stored as varchar(MAX) in the format of:
2019-02-18
However, I want it in the British format dd/mm/yyyy (103).
This is my SQL:
SELECT CONVERT(DATE, DateField, 103) AS "JobStartDate"
FROM tblTest
However, I keep getting this error:
Conversion failed when converting date and/or time from character string.
What am I missing?
Update: The date is initially stored as varchar max as it is coming from a 3rd party system. I have no control over this and I completly understand this is the wrong format, but this is what I have been given.
I have a date stored as varchar(MAX)
There's your problem right there.
Not only you are using the wrong data type to store dates, you are also using max which is a known performance killer.
The solution to the problem is to alter the table and store dates in a Date data type - but first, you must look up all the objects that depends on that column and make sure they will not break or change them as well.
Assuming this can't be done, or as a temporary workaround, you must first convert the data you have to Date, and then convert it back to a string representation of that date using the 103 style to get dd/mm/yyyy.
Since yyyy-mm-dd string format is not culture dependent with the date data type, you can simply do this:
SELECT CONVERT(char(10), TRY_CAST(DateField As Date), 103) As [JobStartDate]
FROM tblTest
Note I've used try_cast and not cast since the database can't stop you from storing values that can't be converted to dates in that column.
You want to format the DateField column and not convert it to date.
So first convert it to DATE and then apply the format:
SELECT FORMAT(CONVERT(DATE, DateField, 21), 'dd/MM/yyyy') AS JobStartDate
See the demo.

How to add an hour in timestamp in sql server (without Declare)

I want to add an hour in the parameter TimeStamp, but not with declare parameter i.e
DECLARE #datetime2 datetime2 = '2019-03-01T09:25:21.1+01:00'
SELECT DATEADD(hour,1,#datetime)
I have a column name TimeStamp in a table and i want to add in all data plus 1 hour.
The column
TimeStamp
2019-03-01T09:25:20.1+01:00
2019-03-01T09:25:21.1+01:00
2019-03-01T09:25:19.1+01:00
I try something like this
SELECT DATEADD(hour,1, TimeStamp), but i have an error
Conversion failed when converting date and/or time from character
string.
Any possible answers ??
Thanks
SELECT DATEADD(hour,1, TimeStamp) is correct
However, The format in TimeStamp is wrong,
So, cast it to DateTime2 First
CAST(TimeStamp as DateTime2)
OR
CAST('2019-03-01T09:25:20.1+01:00' as DateTime2)
So,
SELECT DATEADD(hour, 1, CAST(TimeStamp as DateTime2))
Conversion failed when converting date and/or time from character
string.
The error message means that column TimeStamp stored as a string. DATEADD expects a valid value that is date/datetime/datetime2 or can be converted into it from a string. Because a sample value look like DATETIME2, such extra conversion perhaps is needed:
SELECT DATEADD(hour,1, CAST(TimeStamp as datetime2))
Your syntax will be fine as defined.
It might be a value in your column that is not able to parse to datetime2 because it contains an invalid character.
You could add the ISDATE() to the expression to check if it is valid.
https://learn.microsoft.com/en-us/sql/t-sql/functions/isdate-transact-sql?view=sql-server-2017
edit: forgot to mention you could parse before adding with try_cast or try_convert to datetime2
In Your Timestamp +01:00 represents the Time offset to GMT. You can convert this to your local time and then Add the Hours using DATEADD()
or Remove the Time Offset from the string and add one hour using DATEADD() As suggested by Others.
According to this https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-2017#date-and-time-styles
you have to convert the timestamp with timezone using type 127.
127 is the input format for:
ISO8601 with time zone Z.
yyyy-mm-ddThh:mi:ss.mmmZ (no spaces)
Note: For a milliseconds (mmm) value of 0, the millisecond decimal value will not display. For example, the value '2012-11-07T18:26:20.000 will display as '2012-11-07T18:26:20'.
select convert(datetime2, '2019-03-01T09:25:20.1+01:00', 127)
if you are not using convert and the 127 by using cast you may run in conversion problems depending on language settings of the users.
Maybe you are after this?
select dateadd(hour,1,convert(datetimeoffset, TimeStamp))
Best to not store dates and times as text though.
Edit: Note that his will retain your time zone information if that is important to you.

How to add 1 day from a user defined date in SQL?

What I understood in SQL is if you add 1 day from today's date, you can use
SELECT #date = CONVERT(VARCHAR(8), DATEADD(DAY, 1, GETDATE()), 112)
but my issue is, I am not getting today's date. I have a user defined field for date which I was the one who set this date.
Example: my column is name is "Return Booked", how shall I add 1 day to every return booked I have set?
See attached: SQL Server result
Also, if I try to use CONVERT (DATEADD, *****) I have an error below:
How to deal with the error: Conversion failed when converting date and/or time from character string.
My current SELECT statement is
SELECT dbo.AdditionalDetailInfo.UserDefined6 AS ReturnBooked
Note that the data type of UserDefined6 is nvarchar. :(
Thank you!
You need to change the GETDATE() in the snippet to your value, and it is not a good practice to keep date values in nvarchar, so you will need some conversion first.
something like that:
SELECT CONVERT(VARCHAR(8), DATEADD(DAY, 1, (CONVERT(DATETIME,UserDefined6))),112) AS ReturnBooked
FROM dbo.AdditionalDetailInfo
As datatype of your column is nvarchar, Dateadd function on nvarchar will fail, so First you need to convert the column value to datetime and then use the DateAdd function, like below
Select DATEADD(DAY, 1, CONVERT(Datetime,ReturnBooked))
After looking at the image of sample data, it seems you have a row with date text in wrong format 08/010/2018. The conversion will fail for this particular row, so recommended to fix such bad data.

How to convert SQL Server's timestamp column to datetime format

As SQL Server returns timestamp like 'Nov 14 2011 03:12:12:947PM', is there some easy way to convert string to date format like 'Y-m-d H:i:s'.
So far I use
date('Y-m-d H:i:s',strtotime('Nov 14 2011 03:12:12:947PM'))
SQL Server's TIMESTAMP datatype has nothing to do with a date and time!
It's just a hexadecimal representation of a consecutive 8 byte integer - it's only good for making sure a row hasn't change since it's been read.
You can read off the hexadecimal integer or if you want a BIGINT. As an example:
SELECT CAST (0x0000000017E30D64 AS BIGINT)
The result is
400756068
In newer versions of SQL Server, it's being called RowVersion - since that's really what it is. See the MSDN docs on ROWVERSION:
Is a data type that exposes automatically generated, unique binary numbers within a database. rowversion is generally used as a mechanism
for version-stamping table rows. The
rowversion data type is just an incrementing number and does not
preserve a date or a time. To record a date or time, use a datetime2
data type.
So you cannot convert a SQL Server TIMESTAMP to a date/time - it's just not a date/time.
But if you're saying timestamp but really you mean a DATETIME column - then you can use any of those valid date formats described in the CAST and CONVERT topic in the MSDN help. Those are defined and supported "out of the box" by SQL Server. Anything else is not supported, e.g. you have to do a lot of manual casting and concatenating (not recommended).
The format you're looking for looks a bit like the ODBC canonical (style = 121):
DECLARE #today DATETIME = SYSDATETIME()
SELECT CONVERT(VARCHAR(50), #today, 121)
gives:
2011-11-14 10:29:00.470
SQL Server 2012 will finally have a FORMAT function to do custom formatting......
The simplest way of doing this is:
SELECT id,name,FROM_UNIXTIME(registration_date) FROM `tbl_registration`;
This gives the date column atleast in a readable format.
Further if you want to change te format click here.
Using cast you can get date from a timestamp field:
SELECT CAST(timestamp_field AS DATE) FROM tbl_name
Works fine, except this message:
Implicit conversion from data type varchar to timestamp is not allowed. Use the CONVERT function to run this query
So yes, TIMESTAMP (RowVersion) is NOT a DATE :)
To be honest, I fidddled around quite some time myself to find a way to convert it to a date.
Best way is to convert it to INT and compare. That's what this type is meant to be.
If you want a date - just add a Datetime column and live happily ever after :)
cheers mac
My coworkers helped me with this:
select CONVERT(VARCHAR(10), <tms_column>, 112), count(*)
from table where <tms_column> > '2012-09-10'
group by CONVERT(VARCHAR(10), <tms_column>, 112);
or
select CONVERT(DATE, <tms_column>, 112), count(*)
from table where <tms_column> > '2012-09-10'
group by CONVERT(DATE, <tms_column>, 112);
"You keep using that word. I do not think it means what you think it means."
— Inigo Montoya
The timestamp has absolutely no relationship to time as marc_s originally said.
declare #Test table (
TestId int identity(1,1) primary key clustered
,Ts timestamp
,CurrentDt datetime default getdate()
,Something varchar(max)
)
insert into #Test (Something)
select name from sys.tables
waitfor delay '00:00:10'
insert into #Test (Something)
select name from sys.tables
select * from #Test
Notice in the output that Ts (hex) increments by one for each record, but the actual time has a gap of 10 seconds. If it were related to time then there would be a gap in the timestamp to correspond with the difference in the time.
for me works:
TO_DATE('19700101', 'yyyymmdd') + (TIME / 24 / 60 / 60)
(oracle DB)
Robert Mauro has the correct comment. For those who know the Sybase origins, datetime was really two separate integers, one for date, one for time, so timestamp aka rowversion could just be considered the raw value captured from the server. Much faster.
After impelemtation of conversion to integer
CONVERT(BIGINT, [timestamp]) as Timestamp
I've got the result like
446701117
446701118
446701119
446701120
446701121
446701122
446701123
446701124
446701125
446701126
Yes, this is not a date and time, It's serial numbers
Why not try FROM_UNIXTIME(unix_timestamp, format)?
I had the same problem with timestamp eg:'29-JUL-20 04.46.42.000000000 PM'. I wanted to turn it into 'yyyy-MM-dd' format. The solution that finally works for me is
SELECT TO_CHAR(mytimestamp, 'YYYY-MM-DD') FROM mytable;
I will assume that you've done a data dump as insert statements, and you (or whoever Googles this) are attempting to figure out the date and time, or translate it for use elsewhere (eg: to convert to MySQL inserts). This is actually easy in any programming language.
Let's work with this:
CAST(0x0000A61300B1F1EB AS DateTime)
This Hex representation is actually two separate data elements... Date and Time. The first four bytes are date, the second four bytes are time.
The date is 0x0000A613
The time is 0x00B1F1EB
Convert both of the segments to integers using the programming language of your choice (it's a direct hex to integer conversion, which is supported in every modern programming language, so, I will not waste space with code that may or may not be the programming language you're working in).
The date of 0x0000A613 becomes 42515
The time of 0x00B1F1EB becomes 11661803
Now, what to do with those integers:
Date
Date is since 01/01/1900, and is represented as days. So, add 42,515 days to 01/01/1900, and your result is 05/27/2016.
Time
Time is a little more complex. Take that INT and do the following to get your time in microseconds since midnight (pseudocode):
TimeINT=Hex2Int(HexTime)
MicrosecondsTime = TimeINT*10000/3
From there, use your language's favorite function calls to translate microseconds (38872676666.7 µs in the example above) into time.
The result would be 10:47:52.677
Some of them actually does covert to a date-time from SQL Server 2008 onwards.
Try the following SQL query and you will see for yourself:
SELECT CAST (0x00009CEF00A25634 AS datetime)
The above will result in 2009-12-30 09:51:03:000 but I have encountered ones that actually don't map to a date-time.
Not sure if I'm missing something here but can't you just convert the timestamp like this:
CONVERT(VARCHAR,CAST(ZEIT AS DATETIME), 110)

Average a time value in SQL Sever 2005

I've got a varchar field in SQL Sever 2005 that's storing a time value in the format "hh:mm"ss.mmmm".
What I really want to do is take the average using the built in aggregate function of those time values. However, this:
SELECT AVG(TimeField) FROM TableWithTimeValues
doesn't work, since (of course) SQL won't average varchars. However, this
SELECT AVG(CAST(TimeField as datetime)) FROM TableWithTimeValues
also doesn't work. As near as I can tell, SQL doesn't know how to convert a value with only time and no date into a datetime field. I've tried a wide variety of things to get SQL to turn that field into a datetime, but so far, no luck.
Can anyone suggest a better way?
SQL Server can convert a time-only portion of a datetime value from string to datetime, however in your example, you have a precision of 4 decimal places. SQL Server 2005 only recognizes 3 places. Therefore, you will need to truncate the right-most character:
create table #TableWithTimeValues
(
TimeField varchar(13) not null
)
insert into #TableWithTimeValues
select '04:00:00.0000'
union all
select '05:00:00.0000'
union all
select '06:00:00.0000'
SELECT CAST(TimeField as datetime) FROM #TableWithTimeValues
--Msg 241, Level 16, State 1, Line 1
--Conversion failed when converting datetime from character string.
SELECT CAST(LEFT(TimeField, 12) as datetime) FROM #TableWithTimeValues
--Success!
This will convert valid values into a DATETIME starting on 1900-01-01. SQL Server calculates dates based on 1 day = 1 (integer). Portions of days are then portions of the value 1 (i.e. noon is 0.5). Because a date was not specified in the conversion, SQL Server assigned the value of 0 days (1900-01-01), which accommodates our need to average the time portion.
To perform an AVG operation on a DATETIME, you must first convert the DATETIME to a decimal value, perform the aggregation, then cast back. For example
SELECT CAST(AVG(CAST(CAST(LEFT(TimeField, 12) as datetime) AS FLOAT)) AS DATETIME) FROM #TableWithTimeValues
--1900-01-01 05:00:00.000
If you need to store this with an extra decimal place, you can convert the DATETIME to a VARCHAR with time portion only and pad the string back to 13 characters:
SELECT CONVERT(VARCHAR, CAST(AVG(CAST(CAST(LEFT(TimeField, 12) as datetime) AS FLOAT)) AS DATETIME), 114) + '0' FROM #TableWithTimeValues
Try this
AVG(CAST(CAST('1900-01-01 ' + TimeField AS DateTime) AS Float))
You really should store those in a datetime column anyway. Just use a consistent date for that part (1/1/1900 is very common). Then you can just call AVG() and not worry about it.
I used Cadaeic's response to get an answer I was looking for, so I thought I should share the code....
I was looking for a query that would average ALL my times together and give me an overall Turn Around Time for all approvals. Below is a nested statement that gives you the AVG TAT for individual id's and and when nested an overall TAT
SELECT
-- calculates overall TAT for ALL Approvals for specified period of time
-- depending on parameters of query
CONVERT(VARCHAR, CAST(AVG(CAST(CAST(LEFT(Tat_mins, 12) as datetime) AS FLOAT)) AS DATETIME), 108) + '0'
from
(
-- tat is for individual approvals
SELECT
dbo.credit_application.decision_status,
dbo.credit_application.application_id,
cast(dbo.credit_application.data_entry_complete as date) as'Data Entry Date',
cast(dbo.credit_application.decision_date as DATE) as 'Decision Date',
avg(datediff(minute, dbo.credit_application.data_entry_complete, dbo.credit_application.decision_date)) as 'TAT Minutes',
convert (char(5), DateAdd(minute, Datediff(minute,dbo.credit_application.data_entry_complete, dbo.credit_application.decision_date),'00:00:00'),108) as 'TAT_Mins'
FROM dbo.credit_application
where Decision_status not in ('P','N')
group by dbo.credit_application.decision_status,
dbo.credit_application.data_entry_complete,
dbo.credit_application.decision_date
--dbo.credit_application.application_id
)bb
How do you think to average on datetime?
I guess that you need to GROUP BY some period (Hour?), and display Count(*)?
SQL Server stores datetime data as 2 4-byte integers, hence a datetime take 8 bytes. The first is days since the base date and the second is milliseconds since midnight.
You can convert a datetime value to an integer and perform mathematical operations, but the convert only returns the "days" portion of the datetime value e.g. select convert(int,getdate()). It is more difficult to return the "time" portion as an integer.
Is using SQL Server 2008 an option for you? That version has a new dedicated time data type.
Thanks, Andy.
I'd work out the difference between all of the dates and an arbitrary point (01/01/1900), average it and then add it back on to the arbitrary point.

Resources