convert int values to datetime in sql server - sql

I need to convert the int values of a year, month and day in a datetime using sql server.
actually i' am using this
DECLARE #MONTH INT
DECLARE #YEAR INT
DECLARE #DAY INT
DECLARE #MAXDATE DATETIME
DECLARE #MINDATE DATETIME
SET #MONTH=12
SET #YEAR=2010
SET #DAY=1
SET #MINDATE=CONVERT(DATE,CAST (#YEAR AS VARCHAR)+ RIGHT ('0'+ CAST (#MONTH AS VARCHAR),2) + RIGHT ('0'+ CAST (#DAY AS VARCHAR),2))
SELECT #MINDATE
and works ok, but i'm wondering if exist a better way to convert these values.

This would be a little simpler:
select dateadd(month,(#YEAR-1900)* 12 + #MONTH - 1,0) + (#DAY-1)

I think you definitely have the right way to do this. You're already padding the zeros for single digit months and dates; your solution will work well and is not untidy.
The only other way would be to being with some arbitrary date, and 'add' years, months and days to that starting point. However this is not a great plan, because you would need to start at 31 December, 0 AD by my reckoning. That makes less sense than simply parsing the components, as you are currently doing.

Depending on what you mean by 'better way', you may find different answers acceptable.
For example, converting from a string could be simpler (and thus better) than how it is done in your script. Like this:
SET #MINDATE = CAST(#YEAR AS varchar) + '-' +
CAST(#MONTH AS varchar) + '-' +
CAST(#DAY AS varchar)
That is, if your variable is datetime, the conversion will be implicit, so no need to use CONVERT. The format chosen here is YYYY-MM-DD, or rather YYYY-M-D, which is, as far as I know, acceptable for implicit conversion regardless of locale settings.
EDIT: The format you've chosen, YYYYMMDD, is locale independent too, if I'm not mistaken. My point was only that it required a more complex expression to build the proper string from integers, which seemed to inconvenience you.

Untill i know there´s no way con convert it with a built in function.
If it´s possible to declare the year, month anda day as varchar, it can be easier:
SET DATEFORMAT YMD;
SET #MAXDATE = #YEAR+'/'+#MONTH+'/'+#DAY
SELECT #MAXDATE

Related

cast an integer converted to varchar and appended with a string to a datetime

I can't figure out why this sql code snippet does not work:
cast(cast(b.remodelyear as varchar(5)) + '-01-01' as datetime)
Remodel year is an integer consisting of a year (ex: 2012). I cast it to varchar and append a month and a day to it and then I cast the whole thing to a datetime.
This one works:
cast(cast(Yr as varchar(5)) + '-' + cast(Mth as varchar(5)) + '-' + '01' as datetime)
Where did I go wrong?
Thanks!
Personally, I wouldn't concatenate strings for this, I'd perform some (trivial) date math:
SELECT DATEADD(year, b.remodelyear - 1, '00010101')
FROM <sometable> b
(note that I'm assuming SQL Server - read this blog post for the reasoning behind the date format. If you're using a different RDBMS this'll need to be translated).
I'm curious as to why you're casting to varchar(5), as pretty much every RDBMS I'm aware of would throw an error if it encountered a fifth digit.

How to set part of a datetime

I need to set just the hour of a datetime to a certain value. I know I can add it the difference to the desired value, or create a new datetime with parts from the original one, but isn't there a cleaner way? Something like:
declare #d datetime = '09/08/2012 09:14:55'
set #d = SETDATEPARTORSOMETHINGLIKETHAT (hour, #d, 23)
Thanks a lot.
DECLARE #TargetHour TINYINT = 23;
DECLARE #d datetime = '09/08/2012 09:14:55';
SET #d = DATEADD(HOUR, #TargetHour - DATEPART(HOUR, #d), #d);
SELECT #d;
Result:
2012-09-08 23:14:55.000
(And yes, this will work if the #TargetHour is less than the current hour, e.g. 5 or 7.)
I'd be very careful though about using ambiguous and error-prone formats like m/d/y. Case in point: I don't even know if you meant September 8th or August 9th, and SQL Server isn't going to know either - it needs to use regional settings etc. to figure it out, and if you give your code to someone with different settings, it will generate an error or, even worse, accept the wrong date silently. You should use:
DECLARE #d datetime = '2012-09-08T09:14:55';
Bad habits to kick : mis-handling date / range queries

Conversion failed converting datetime from string

I am trying to convert my three parameters to a DATETIME but its not working. I get the error that the conversion failed when converting datetime from character string whenever I run this query. Perhaps I am doing in wrong in the conversion? If anyone can provide any feedback.
#month varchar,
#day varchar,
#year varchar
AS
DECLARE #date DATETIME
SET #date = Convert(DateTime, #month + '/' + #day + '/' + #year, 101)
Select *
From events
Where (EDate = #date) OR EDateEnd = #date OR #date Between EDate AND EDateEnd
Order By EDate ASC
You need to set the size of your parameters. Probably something like
#month varchar(2),
#day varchar(2),
#year varchar(4)
That should be working. Make sure you have provided valid values in you parameters.
Update
You should lose the 101 parameter for conversion. Provided that parameters are informed with valid values, this should work for both 2-digit and 4-digit years:
SET #date = Convert(DateTime, #month + '/' + #day + '/' + #year)
This is just a guess, because the conversion function shown should work with the proper parameters.
Are you passing in the year as a two-digit number? If so, try passing it as the full four digit year (which the "101" format expects) OR change it to
SET #date = Convert(DateTime, #month + '/' + #day + '/' + #year, 1)
if you're passing in a 2 digit year.
(See the difference for with century and without century here: http://msdn.microsoft.com/en-us/library/ms187928.aspx)
EDIT
I have a second guess... The error may not be on the line where you're explicitly converting the parameters into a Datetime variable. This has burned me before... The error MAY be occurring on the following line:
Where (EDate = #date) OR EDateEnd = (#date) OR #date Between EDate AND EDateEnd
if the EDate column or EDateEnd column is not necessaryly a DateTime column. It could be that THOSE contain the values that can't be converted to a DateTime. (They could be char fields, with a DateTime string stored in them, or they could be actual Date fields with null values stored in them.)
However, without more information about the actual schema of the database it's hard to tell. The best we can do is guess.

SQL Fastest way to compare two dates (non standard varchar format and datetime)

I have two "date" fields that I need to join on.
The first is a normal datetime in the format yyyy-mm-dd hh:mm:ss
The second is a varchar(8) in the red-headed step child format mmddyyyy
Now this gets painful because there is no easy way to convert to the corresponding type. There is a built-in format that is yyyymmdd but that doesn't match the varchar format.
There are two paths I can see:
declare #normal_date as datetime;
declare #hated_date as varchar(8);
set #normal_date='1974-11-01 00:00:00.000'
set #hated_date='11011974'
--cast to date time with string splits
select #normal_date
where CONVERT(datetime, RIGHT(#hated_date,4)+LEFT(#hated_date,2)+SUBSTRING(#hated_date,3,2))=#normal_date
--convert normal date to ackward format
select #normal_date
where REPLACE(CONVERT(varchar(10),#normal_date,101), '/','')=#hated_date
Which is better? Or is there a better way?
Edited to show costs
--Operator cost (39%)
CONVERT(datetime, RIGHT(#hated_date,4)+LEFT(#hated_date,2)+SUBSTRING(#hated_date,3,2))=#normal_date
--Operator cost (57%)
REPLACE(CONVERT(varchar(10),#normal_date,101), '/','')=#hated_date
--Operator cost (46%)
cast(stuff(stuff(#hated_date, 3,0, '/'),6,0,'/') as datetime)=#normal_date
--Operator cost (47%)
RIGHT(#hated_date, 4) + LEFT(#hated_date, 4)=#normal_date
This is yyyymmdd no?
RIGHT(#hated_date, 4) + LEFT(#hated_date, 4)
So, your script becomes
declare #normal_date as datetime;
declare #hated_date as varchar(8);
set #normal_date='1974-11-01 00:00:00.000'
set #hated_date='11011974'
--SELECT #hated_date = RIGHT(#hated_date, 4) + LEFT(#hated_date, 4))
select 'hurrah' WHERE #normal_date = RIGHT(#hated_date, 4) + LEFT(#hated_date, 4)
Another approach is this:
MONTH(#normal_date)*1000000 + DAY(#normal_date)*10000 + YEAR(#normal_date)
=
CAST(#hated_date AS INT)
one more thing: it is more precise to compare real execution costs than to rely on the optimizer's estimates.
Try this:
select cast(stuff(stuff('11011974', 3,0, '/'),6,0,'/') as datetime)
Update
Suggest you either fix the column to be datetime or add a datetime column to the table and convert the data so that you only have to do this conversion once when the data is entered (and once of course for existing data) This could probaly even be a calculated column. This is NOT something you want to be doing in select statements. If necessary create a dateconversion table with every opossible date in both formates and join to it if the table can't be changed.
You might also want to check to make sure there are no invalid dates in there which is always a possibility with storing dates in a data type other than a datetime one.

Convert varchar into datetime in SQL Server

How do I convert a string of format mmddyyyy into datetime in SQL Server 2008?
My target column is in DateTime
I have tried with Convert and most of the Date style values however I get an error message:
'The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.'
OP wants mmddyy and a plain convert will not work for that:
select convert(datetime,'12312009')
Msg 242, Level 16, State 3, Line 1
The conversion of a char data type to a datetime data type resulted in
an out-of-range datetime value
so try this:
DECLARE #Date char(8)
set #Date='12312009'
SELECT CONVERT(datetime,RIGHT(#Date,4)+LEFT(#Date,2)+SUBSTRING(#Date,3,2))
OUTPUT:
-----------------------
2009-12-31 00:00:00.000
(1 row(s) affected)
SQL Server can implicitly cast strings in the form of 'YYYYMMDD' to a datetime - all other strings must be explicitly cast. here are two quick code blocks which will do the conversion from the form you are talking about:
version 1 uses unit variables:
BEGIN
DECLARE #input VARCHAR(8), #mon CHAR(2),
#day char(2), #year char(4), #output DATETIME
SET #input = '10022009' --today's date
SELECT #mon = LEFT(#input, 2), #day = SUBSTRING(#input, 3,2), #year = RIGHT(#input,4)
SELECT #output = #year+#mon+#day
SELECT #output
END
version 2 does not use unit variables:
BEGIN
DECLARE #input CHAR(8), #output DATETIME
SET #input = '10022009' --today's date
SELECT #output = RIGHT(#input,4) + SUBSTRING(#input, 3,2) + LEFT(#input, 2)
SELECT #output
END
Both cases rely on sql server's ability to do that implicit conversion.
Likely you have bad data that cannot convert. Dates should never be stored in varchar becasue it will allow dates such as ASAP or 02/30/2009. Use the isdate() function on your data to find the records which can't convert.
OK I tested with known good data and still got the message. You need to convert to a different format becasue it does not know if 12302009 is mmddyyyy or ddmmyyyy. The format of yyyymmdd is not ambiguous and SQL Server will convert it correctly
I got this to work:
cast( right(#date,4) + left(#date,4) as datetime)
You will still get an error message though if you have any that are in a non-standard format like '112009' or some text value or a true out of range date.
I found this helpful for my conversion, without string manipulation. https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql
CONVERT(VARCHAR(23), #lastUploadEndDate, 121)
yyyy-mm-dd hh:mi:ss.mmm(24h) was the format I needed.
Convert would be the normal answer, but the format is not a recognised format for the converter, mm/dd/yyyy could be converted using convert(datetime,yourdatestring,101) but you do not have that format so it fails.
The problem is the format being non-standard, you will have to manipulate it to a standard the convert can understand from those available.
Hacked together, if you can guarentee the format
declare #date char(8)
set #date = '12312009'
select convert(datetime, substring(#date,5,4) + substring(#date,1,2) + substring(#date,3,2),112)
Look at CAST / CONVERT in BOL that should be a start.
If your target column is datetime you don't need to convert it, SQL will do it for you.
Otherwise
CONVERT(datetime, '20090101')
Should do it.
This is a link that should help as well:
I'd use STUFF to insert dividing chars and then use CONVERT with the appropriate style. Something like this:
DECLARE #dt VARCHAR(100)='111290';
SELECT CONVERT(DATETIME,STUFF(STUFF(#dt,3,0,'/'),6,0,'/'),3)
First you use two times STUFF to get 11/12/90 instead of 111290, than you use the 3 to convert this to datetime (or any other fitting format: use . for german, - for british...) More details on CAST and CONVERT
Best was, to store date and time values properly.
This should be either "universal unseparated format" yyyyMMdd
or (especially within XML) it should be ISO8601: yyyy-MM-dd or yyyy-MM-ddThh:mm:ss More details on ISO8601
Any culture specific format will lead into troubles sooner or later...
use Try_Convert:Returns a value cast to the specified data type if the cast succeeds; otherwise, returns null.
DECLARE #DateString VARCHAR(10) ='20160805'
SELECT TRY_CONVERT(DATETIME,#DateString)
SET #DateString ='Invalid Date'
SELECT TRY_CONVERT(DATETIME,#DateString)
Link:MSDN TRY_CONVERT (Transact-SQL)
I had luck with something similar:
Convert(DATETIME, CONVERT(VARCHAR(2), #Month) + '/' + CONVERT(VARCHAR(2), #Day)
+ '/' + CONVERT(VARCHAR(4), #Year))
The root cause of this issue can be in the regional settings - DB waiting for YYYY-MM-DD while an app sents, for example, DD-MM-YYYY (Russian locale format) as it was in my case. All I did - change locale format from Russian to English (United States) and voilà.
This seems the easiest way..
SELECT REPLACE(CONVERT(CHAR(10), GETDATE(), 110),'-','')
SQL standard dates while inserting or updating Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
So if you are inserting/Updating below 1/1/1753 you will get this error.
DECLARE #d char(8)
SET #d = '06082020' /* MMDDYYYY means June 8. 2020 */
SELECT CAST(FORMAT (CAST (#d AS INT), '##/##/####') as DATETIME)
Result returned is the original date string in #d as a DateTime.