Converting an irregular varchar to datetime in sql server - sql

I'm working on revamping a database right now, and all the datetime's are stored in varchar's formatted like so: DDMonYY hhmm (ex. 13Mar99 2032).
I don't have a lot of experience with SQL, as I only just finished my first year of college so I'm having a really hard time trying to get this to work so any help would be appreciated.

All you should need to do for your particular string is to get a colon in between the hour and minute values. Something like:
SELECT CAST(STUFF('13Mar99 2032', LEN('13Mar99 2032') - 1, 0, ':') AS datetime)
should work.

You can pick a datetime format and then shift parts of the string to match it. For example, format 7 is:
select convert(varchar(25), getdate(), 7)
-->
'Jun 23, 14'
So you can use substring to transform your string:
declare #orig varchar(30) = '13Mar99 2032'
declare #conv varchar(30)
select #conv = substring(#orig, 3, 3) + ' ' + substring(#orig, 1, 2) + ', ' +
substring(#orig, 6, 2) + ' ' + substring(#orig, 9, 2) + ':' + substring(#orig, 11, 2)
select #conv
, convert(datetime, #conv, 7)
-->
'Mar 13, 99 20:32' 1999-03-13 20:32:00.000

Related

How convert SQL Server DATE columns to DD:MM:YY and HH:MM:SS

I have a SQL Server column which is called DATE with this sample data 19452801102747.
I have this code
SELECT REPLACE(CONVERT(CHAR(10), [DATE], 103), '/', '')
I can get the date okay, is the final part of converting HH:MM:SS.
I am using SSMS 2018 and I would like to have two column separate; columns as shown on below image (DATE(DD:MM:YYYY))(TIME(HH:MM:SS))
Many thanks for your help.
We can use a simple substring to add date time separator in your varchar string,
because we cannot directly convert varchar to datetime..
DECLARE #date varchar(50) = '19452801102747' declare #date1 varchar(50)
SET
#date1 = SUBSTRING(#date, 1, 4) + '-' + substring(#date, 7, 2) + '-' + substring(#date, 5, 2) + ' ' + substring(#date, 9, 2) + ':' + substring(#date, 11, 2) + ':' + substring(#date, 13, 2)
SELECT convert(datetime, #date1)
First of all: You should not store datetime values in a non-appropriate datatype.
Your example looks like YYYYddMMHHmmss. There is no out of the box conversion for this...
The following will perform a number of string methods in order to transform your own format to a standard format. In this case I chose ISO8601, which is YYYY-MM-ddTHH:mm:ss:
DECLARE #YourDate VARCHAR(100)='19452801102747';
SELECT CONVERT(DATETIME,STUFF(LEFT(#YourDate,4) + STUFF(STUFF(STUFF(STUFF(SUBSTRING(#YourDate,7,1000),7,0,':'),5,0,':'),3,0,'T'),1,0,'-'),8,0,'-' + SUBSTRING(#YourDate,5,2)),126);
The STUFF() calls will insert some characters in the right position. Furthermore some string cutting will swap your ddMM to MMdd.

SQL Server : converting varchar field to date

I have in my table a varchar column with bunch of dates in the following format dd-MM-yyyy
31-12-2018
01-01-2019
02-01-2019
I need to write a date based query that gets all the dates before 01-01-2019.
I have tried using both CAST and CONVERT to convert these table values without luck.
Using CAST, my code is below:
SELECT
CAST('''' + SUBSTRING(arc_billed_to_date, 4, 2) + '-' + SUBSTRING(arc_billed_to_date, 1, 2) + SUBSTRING(arc_billed_to_date, 6, 5)+ '''' AS date),
CAST('''' + SUBSTRING(arc_billed_to_date, 7, 5) + '-' + SUBSTRING(arc_billed_to_date, 1, 2) + '-' + SUBSTRING(arc_billed_to_date, 4, 2) + '''' AS date),
CAST('''' + SUBSTRING(arc_billed_to_date, 7, 5) + '-' + SUBSTRING(arc_billed_to_date, 4, 2) + '-' + SUBSTRING(arc_billed_to_date, 1, 2) + '''' AS DATE),
CONVERT(DATE, '12-31-2018') AS x
FROM
wkpol
Using Convert
select Convert(datetime,'''' + SUBSTRING(arc_billed_to_date,7,5) + '-' + SUBSTRING(arc_billed_to_date,4,2) + '-' + SUBSTRING(arc_billed_to_date,1,2)+ '''',105) as x from wkpol
The error I get is
Conversion failed when converting date and/or time from character string.
Any help is appreciated.
SELECT *
FROM wkpol
WHERE convert(date, arc_billed_to_date, 103) < convert(date, '01/01/2019');
Well you are going to get many blames for using varchar field for date. Anyway, assuming it is a matter of another thread you can do the conversion like:
select * from myTable
where cast(right(arc_billed_to_date,4) +
substring(arc_billed_to_date,4,2) +
left(arc_billed_to_date,2) as date) < '20190101';
You wouldn't be using any index either.
In addition to Sean's comments, you can also set the DateFormat as DMY
Example
Declare #YourTable table (SomeCol varchar(50))
Insert Into #YourTable values
('31-12-2018')
,('01-01-2019')
,('02-01-2019')
Set DateFormat DMY
Select AsDate = try_convert(date,SomeCol)
From #YourTable
Returns
AsDate
2018-12-31
2019-01-01
2019-01-02

SQL Server Parse decimal to DateTime

I have a table in SQL Server 2017. In this table date stores as a decimal in next format:
20180717164540.2200000
YYYYMMDDhhmiss.nnnnnnn
4 digits for the year, 2 digits for a calendar month, 2 digits for a day of a month, 2 digits for a 24-hour based hour of the day in UTC, 2 digits for a minute of an hour, 2 digits for seconds of a minute, and fractional seconds.
My aim is to transform this format into DateTime and store it in another table in a database.
So my question is how to convert this format to DateTime format in SQL Server. As far as I know, you can not create custom date format like in Oracle.
I tried a lot of times with FORMAT AND CONVERT MSSQL functions but it not gonna work.
SELECT FORMAT(CONVERT(NVARCHAR(22), DECIMALCOLUMN), 'YYYYMMDDhhmiss') FROM SOURCE-TABLE;
Thank you for your help!
You were really close with your FORMAT idea. FORMAT gives you an NVARCHAR output, which you can explicitly CAST as a DATETIME2(7) (which maintains your precision level).
DECLARE #dateWannaBe DECIMAL(21,7) = 20180717164540.2200000;
SELECT CAST(FORMAT(#dateWannaBe,'####-##-## ##:##:##.#######', 'en-US') AS DATETIME2(7)) AS ActualDateTime2;
+-----------------------------+
| ActualDateTime2 |
+-----------------------------+
| 2018-07-17 16:45:40.2200000 |
+-----------------------------+
EDIT: Added the culture parameter to the FORMAT function per #JeroenMostert's comment.
a lot of stuffing
declare #dt decimal(30,8) = 20180717164540.2200000
select #dt, convert(datetime2,
stuff(
stuff(
stuff(
convert(varchar(30), #dt),
9, 0, ' '),
12, 0, ':'),
15, 0, ':')
)
/* RESULT
20180717164540.22000000 2018-07-17 16:45:40.2200000
*/
Try this:
DECLARE #date DECIMAL (30,7) =20180717164540.2200000
SELECT CONVERT(DATETIME, SUBSTRING(CONVERT(VARCHAR, #date),1,4) + '-' + SUBSTRING(CONVERT(VARCHAR, #date),5,2)
+ '-' + SUBSTRING(CONVERT(VARCHAR, #date),7,2) + ' ' + SUBSTRING(CONVERT(VARCHAR, #date),9,2) + ':' +
SUBSTRING(CONVERT(VARCHAR, #date),11,2) + ':' + SUBSTRING(CONVERT(VARCHAR, #date),13,2) + '.' + SUBSTRING(CONVERT(VARCHAR, #date),16,2))
You need SUBSTRING() function with stuff() :
select dateadd(ss, datediff(ss, 0, cast(stuff(stuff(substring(cast(#date as varchar(30)), 9, 20), 3, 0, ':'), 6, 0, ':') as datetime2)),
substring(cast(#date as varchar(10)), 1, 8)
)
. . .
DECLARE #TIME DECIMAL(38,8)
SET #TIME = '20180717164540.2200000'
SELECT CAST([DT] AS DATETIME) FROM(
SELECT LEFT(CAST(#TIME AS VARCHAR),4) +
SUBSTRING(CAST(#TIME AS VARCHAR),5,2) +
SUBSTRING(CAST(#TIME AS VARCHAR),7,2) + ' ' +
SUBSTRING(CAST(#TIME AS VARCHAR),9,2) + ':'+
SUBSTRING(CAST(#TIME AS VARCHAR),11,2) + ':' +
SUBSTRING(CAST(#TIME AS VARCHAR),13,2) AS DT
) AS X
Another approach, using LEFT, SUBSTRING and RIGHT
DECLARE #str nvarchar(22) = '20180717164540.2200000'
SELECT CONVERT(datetime2,
LEFT(#str,4)+
SUBSTRING(#str,5,2)+
SUBSTRING(#str,7,2)+' '+
SUBSTRING(#str,9,2)+':'+
SUBSTRING(#str,11,2)+':'+
SUBSTRING(#str,13,2)+'.'+
RIGHT(#str,7))
You could stuff and use DateTime2 instead of DateTime:
select
cast(stuff(stuff(stuff(
cast(mydate as varchar(30)),
13,0,':'),
11,0,':'),
9,0,' ') as datetime2) as myDateTime from myTable;

Date Conversion of yymmddhhmm.yymmddhhmm in SQL

I'm getting this type of data in DateandTime Column in SQl.
1803301611.1803301611
Format is yymmddhhmm.yymmddhhmm and I have to convert this data in a date format.
The DateandTime Column date type is Varchar(5)
I don't think the format of your time string can be directly converted by SQL Server. But, we can try to piece together into a format which can be. This is the closest I could come, and it required prepending a 20 in front of the year to make a full 4 digit century:
SELECT
col AS input,
CONVERT(datetime, '20' + SUBSTRING(col, 1, 2) + '-' + SUBSTRING(col, 3, 2) + '-' +
SUBSTRING(col, 5, 2) + ' ' + SUBSTRING(col, 7, 2) + ':' +
SUBSTRING(col, 9, 2), 120) AS output
FROM yourTable;
Demo
We ideally should have been able to use mask 20 without the century, but I could not get it to work.
You can do :
select *, cast(concat(cast(left(col, 6) as date), ' ',stuff(right(col, 4), 3, 0, ':')
) as datetime
) as newdatetime
from table t;

How can I find out which data won't cast?

I have a SQL table with a date field defined as char(8), or 20090609, and a time field defined as char(4), or 1230. I am moving this data into another table and I want to combine the two fields and put them in a smalldatetime field in the new table. My query is like this:
INSERT NewTable(eventdate)
SELECT
CAST((datecol + ' ' + substring(timecol, 1, 2) + ':' + substring(timecol, 3, 2)) as smalldatetime)
FROM OldTable
When I run this, I get an error:
The conversion of char data type to
smalldatetime data type resulted in an
out-of-range smalldatetime value.
I've tried checking len(datecol) and len(timecol) to make sure that they are at least the correct number of characters. I have no idea how I can find the offending data, any suggestions? The database is SQL2000 and I'm using SMO 2008.
Try this:
SELECT datecol, timecol
FROM OldTable
WHERE ISDATE(datecol + ' ' + substring(timecol, 1, 2) + ':' + substring(timecol, 2, 2)) = 0
That will show you which rows cannot be converted successfully.
It is probably out of the range of acceptable smalldatetime values
January 1, 1900, through June 6, 2079
EDIT On closer inspection I think the substring parameters for the second portion of the time may be incorrect (which may be the whole problem) updated below to reflect substring(timecol, 3, 2)
New Approach this sql does assume that all dates are 8 characters in length, and all times are 4.
Select SubString(DateCol, 1, 4) as tehYear,
Substring(DateCol, 5,2) as tehMonth,
SubString(DateCol, 7,2) as tehDay,
SubString(TimeCol, 1,2) as tehHour,
Substring(TimeCOl, 3,4) as tehMinute,
*
from OldTable
where
(SubString(DateCol, 1,4) > 9999 or SubString(DateCol, 1,4) < 1753)
OR (Substring(DateCol, 5,2) > 12 or Substring(DateCol, 5,2) < 1)
OR (SubString(DateCol, 7,2) > 31 or SubString(DateCol, 7,2) < 1)
OR (SubString(TimeCol, 1,2) > 23 or(SubString(TimeCol, 1,2) < 0)
OR (Substring(TimeCOl, 3,4) > 59 or Substring(TimeCOl, 3,4) <0)
Try casting to datetime and seeing if there are any dates that fall outside of that range to identify your problem data.
SELECT
CAST((datecol + ' ' + substring(timecol, 1, 2) + ':' + substring(timecol, 3, 2))
as datetime)
FROM OldTable
Where CAST((datecol + ' ' + substring(timecol, 1, 2)
+ ':' + substring(timecol, 3, 2)) as datetime)
> Cast('06/06/2079' as datetime) or CAST((datecol + ' '
+ substring(timecol, 1, 2) + ':' + substring(timecol, 3, 2)) as datetime)
< Cast('01/01/1900' as datetime)
If you run the query in query analyzer it should tell you what row the error occured!