SQL Server String Parsing - sql-server-2005

I have SQL Server 2005 and all dates are stored using a DATETIME column type. The front-end application handles dates in a "yyyyMMdd hhmmss" format. I'm writing a set of SQL queries and stored procedures and was wondering if there is an easy way to convert this format to the standard SQL DATETIME. I did not code the front-end app so I cannot make any changes to it.
I have looked into CONVERT(), but none of the type codes match what I want. The closest one is
CONVERT(DATETIME, '20101017' 112)
But that does not have the time component of the input. Any ideas? or do I have to write a SQL function to do that parsing and conversion.
Thank you,

If you insert the colons into the appropriate places in your time, you can use style 120.
declare #d varchar(15)
set #d = '20101017 111428'
select CONVERT(DATETIME, stuff(stuff(#d,12,0,':'),15,0,':'), 120)

You might find this page to be useful (if you can get past the psychosis-inducing color scheme).

How about this:
declare #s as varchar(25)
set #s = '20101109 172054'
select #s, convert(datetime, SUBSTRING(#s, 1, 4) + '-' + SUBSTRING(#s, 5, 2)
+ '-' + SUBSTRING(#s, 7, 3) + SUBSTRING(#s, 10, 2) + ':'
+ SUBSTRING(#s, 12, 2) + ':' + SUBSTRING(#s, 14, 2), 20)

Related

Is there a simpler method for getting the two digit year?

EDIT: Forced to use 2008 R2
I need to get the two digit year to appended to an invoice number (for simplicity sake I am using a test variable). Previously I only needed the month and day appended but the customer is now asking for the two digit year.
My Method: REPLACE + SUBSTRING + STR + YEAR(variable DATETIME)
REPLACE((SUBSTRING(STR (Year(#Date),4),3,2)), ' ', '0')**
My code:
DECLARE #TestVariable AS VARCHAR(100),
#Date as datetime = GetDate()
SET #TestVariable = '1234'
+ REPLACE(STR(MONTH(#Date), 2), ' ', '0')
+ REPLACE(STR(DAY(#Date), 2), ' ', '0')
+ REPLACE((SUBSTRING(STR (Year(#Date),4),3,2)), ' ', '0')
PRINT #TestVariable
Honestly, just don't work with 2 digit years any more; learn the lessons of last century's mistake and use 4 digits.
If you "have" to, then you could use CONVERT with a style code, and then just replace the characters with an empty string:
DECLARE #TestVariable varchar(100) = '1234',
#Date datetime = GETDATE();
SELECT #TestVariable + REPLACE(CONVERT(varchar(8),#Date, 1),'/','');
You can simplify the whole process, not just the year portion. Using FORMAT you can accomplish this easily.
DECLARE #TestVariable AS VARCHAR(100) = '1234'
, #Date as datetime = GetDate()
Select #TestVariable + FORMAT(#Date, 'MMddyy')
select replace(convert(varchar(20),#date,1)'/','') --or any other you need
See the docs
I'll echo others' sentiment of "do you really have to use a two-digit year"? But if you have to, I like this sort of thing
set #TestVariable = '1234'
+ right('0' + cast(month(#date) as varchar(2)), 2)
+ right('0' + cast(day(#date) as varchar(2)), 2)
+ right('0' + cast(year(#date) % 100 as varchar(2)), 2);
To talk through the general approach, I'm using right('0', «something», 2) as a means to zero pad to two places, using cast(«something» as varchar(2)) to get a string instead of a number (so implicit conversion doesn't just add zero and the relevant datepart), and finally year(#date) % 100 to get the last two digits of the date.

Conversion failed when converting date and/or time from character string while using the function

I have a function that returns a datetime2.
...
MS_VatToDate (#vYEAR smallint, #vMONTH smallint, #vDAY smallint)
...
DECLARE #VatDate DATETIME2;
DECLARE #VatDateText VARCHAR(11);
SET #VatDateText = CAST(#vYEAR AS VARCHAR(4)) + '-' +
CAST(#vMONTH AS VARCHAR(2)) + '-' +
CAST(#vDAY AS VARCHAR(2));
SET #VatDate = CONVERT(DATETIME2, #VatDateText, 126);
RETURN(#VatDate);
When I specify data it works just fine, but when I specify some range I get an error.
Conversion failed when converting date and/or time from character string.
The same thing happened when I tried to apply this function for whole database, but at start I'm getting correct result and then at the end it's the same error.
Why are you writing your own function?
SQL Server offers datefromparts(), so you an just write:
select datefromparts(2018, 11, 30)
If you want a datetime2:
select convert(datetime2, datefromparts(2018, 11, 30))
Or datetime2fromparts():
select datetime2fromparts(2018, 11, 30, 0, 0, 0)
Support for SQL Server 2008 R2 ends in July, 2019, so you should update before support ends.
In the older system, you can convert without a format -- unless your default date format is YDM:
set #VatDateText = cast(#vYEAR as varchar(4))+'-'+cast(#vMONTH as varchar(2))+'-'+cast(#vDAY as varchar(2));
set #VatDate = convert(datetime2, convert(date, #VatDateText));
I suppose you can use ISDATE function prior to conversion:
DECLARE #VatDate datetime2;
DECLARE #VatDateText varchar(11);
SET #VatDateText = CAST(#vYEAR as varchar(4)) + '-' + CAST(#vMONTH as varchar(2)) + '-' + CAST(#vDAY as varchar(2));
IF ISDATE(#VatDateText) = 1
SET #VatDate = convert(datetime2, #VatDateText, 126);
ELSE
PRINT #VatDateText + ' is invalid';
SELECT /* RETURN */ #VatDate;
If you can't use DATEFROMPARTS (it is available since SQL Server 2012), remove the dashes and cast the string directly. '20181130' will be successfully converted to date, regardless of your locale and dates settings. In this case it could also be that you have single digit month/day in your data and the constructed string is not valid, so add leading zeroes.
declare #VatDate datetime2;
declare #VatDateText varchar(11);
set #VatDateText = cast(#vYEAR as varchar(4))+right('0' +cast(#vMONTH as varchar(2)), 2)+right('0' + cast(#vDAY as varchar(2)), 2);
set #VatDate = cast(#VatDateText as datetime2);
return(#VatDate);

Possible to avoid repetition of expression in a QUERY

I have to display time in a weird format.
For example, if time is 15:30:45.5000, I need to display "153045.5".
To do this, I have the following query:
SELECT LEFT(CONVERT(varchar(20), GETDATE(), 114), 2) +
SUBSTRING(CONVERT(varchar(20), GETDATE(), 114), 4, 2) +
SUBSTRING(CONVERT(varchar(20), GETDATE(), 114), 7, 2) + '.' +
SUBSTRING(CONVERT(varchar(20), GETDATE(), 114), 10, 1);
Is there anything I can do to avoid repeating the expression CONVERT(varchar(20), GETDATE(), 114)?
Edit:
I saw a really cool answer here which was deleted for some reason after I refreshed the page, but it gave me the idea to think of an alternative solution:
SELECT REPLACE(RIGHT(CONVERT(varchar(21), getdate(), 126), 10), ':', '')
Although this answer doesn't solve the original question in a generic way, it still solves my problem in a different way.
In addition to functions in other answers, you can calculate a partial result in a common table expression (CTE) or inline view:
; WITH gd(getDate_114)
AS (SELECT CONVERT(VARCHAR(20), GETDATE(), 114))
SELECT LEFT(getDate_114, 2)
+ SUBSTRING(gd.getDate_114, 4, 2)
+ SUBSTRING(gd.getDate_114, 7, 2)
+ '.'
+ SUBSTRING(gd.getDate_114, 10, 1)
FROM gd
Unfortunately, unless I'm mistaken, there isn't a way to minimize this in SQL Server 2008 R2. You'll have to construct it the way you're already doing it. Another option (as already pointed out by #jonasnas) would be to create a function that returns the format of the current date.
If you are able/willing to upgrade to SQL Server 2012, however, you can take advantage of the FORMAT() function to format the string:
Select Format(GetDate(), N'HHmmss.f')
Wrap all the formatting code in a function
create function dbo.FormatTime (#time datetime)
returns varchar(20)
as
begin
return (select LEFT(CONVERT(varchar(20), #time, 114), 2)
+ SUBSTRING(CONVERT(varchar(20), #time, 114), 4, 2)
+ SUBSTRING(CONVERT(varchar(20), #time, 114), 7, 4))
end
And use it as
select dbo.FormatTime(getdate())
To avoid repetition in the function body, you can store the #time converted to varchar in a variable
declare #dateAsVarchar varchar(20) = CONVERT(varchar(20), #time, 114)
return (select LEFT(#dateAsVarchar, 2)
+ SUBSTRING(#dateAsVarchar, 4, 2)
+ SUBSTRING(#dateAsVarchar, 7, 4))

Converting separate columns for mm, dd, and yr into a workable mm/dd/year format

Basically I have 3 separate columns in a table. I will call them SMonth, Sday, Syear. They are stored as numeric values for some reason. I can use the following string to format them into what looks like a date but doesn't allow me to use functions such as sort, order by, datediff or dateadd.
CAST(SMonth AS varchar(2)) + '/' + CAST(SDay varchar(2)) + '/' + CAST(SYear AS varchar(4))
Anyone know how to convert this into a workable date, without changing the table?
It doesn't matter how it looks as long as I can use it ie a date or datetime makes no difference.
Thanks in advance.
Just convert your result into a date or datetime.
DECLARE #SMonth AS INT = 12
DECLARE #SDay AS INT = 31
DECLARE #SYear as INT = 2013
SELECT CONVERT(DATE,CAST(#SMonth AS varchar(2)) + '/' + CAST(#SDay AS varchar(2)) + '/' + CAST(#SYear AS varchar(4)))
you should convert format the string as yyyy/mm/dd in order to make sure that SQL Server uses ODBC canonical format
SELECT CONVERT(date, CONVERT(varchar, Syear) + '/' + convert(VARCHAR, SMonth) + '/' + convert(VARCHAR, SDay ) )
Otherwise it your results could depend on the default dateformat or someone changed it using SET DATEFORMAT, for example:
05/10/2013 could mean
May 10, 2013 if the DATEFORMAT is U.S.
October 5, 2013 if the DATEFORMAT is Brithish / French
see this for complete reference of dateformat

Add characters in the variable

I need to make the string/varchar variable with value 20061212 to be string/varchar value 2006-12-12 00:00:00
I can't find the right SQL syntax code to make it happened in SQL Server.
The code can be created as stored procedure or similar in SQL Server.
SELECT
LEFT(#string, 4)
+ '-' + SUBSTRING(#string, 5, 2)
+ '-' + SUBSTRING(#string, 7, 2)
+ ' 00:00:00'
You could cast your string to a DATETIME and then convert it back to a string in your chosen format. But that would likely be slower than this more explicit option.
SELECT
CONVERT(VARCHAR(19), CAST(#string AS DATETIME), 120)
You can use stuff
declare #s varchar(8) = '20061212'
select stuff(stuff(#s, 7, 0, '-'), 5, 0, '-')+' 00:00:00'
You can use the SUBSTRING() function (detailed here: http://www.sql-statements.com/sql-substring.html) to take apart the original string, and then put the pieces back together with the added dashes & time at the end using the concatenation operator +.
Culture independent variant:
SELECT CONVERT(varchar, convert(datetime, '20061212', 112), 120)
BUT this only valid for DATETIME-allowed range of dates, use DATETIME2 instead