I have a varchar(200) column called Submit_Date and I am trying to convert it to MM/DD/YYYY format. When I do that I get the following error:
Msg 242, Level 16, State 3, Line 1The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
Sample Data of the table is:
Submit_Date
-----------------------
27-09-2013 16:15:00 CST
30-09-2013 16:30:24 CST
27-09-2013 10:03:46 CST
I tried the following:
Select Convert(datetime,Submit_date,101) from dbo.Tickets
You've committed about 15 cardinal sins about date/time here. First, the quick answer:
DECLARE #x VARCHAR(200);
SELECT #x = '27-09-2013 16:15:00 CST'
SELECT CONVERT(CHAR(10),CONVERT(DATETIME,LEFT(#x,10),105),101);
Next:
Why on earth are you storing date/time data in a varchar(200) column? You are aware that anyone can insert values like '09-27-2013' or '465-32-207floob' in there, right? If you need time zone information you can look at the DATETIMEOFFSET data type (but note that it is not DST-aware).
Why are you storing a regional format like dd-mm-yyyy? If the first value were 07-11-2013 I'd have to guess if you meant July 11 or November 7. If you're not going to do it right and use a proper date/time data type, why use a string format that makes people guess? You are much better off with a format that is unambiguous, such as yyyy-mm-ddThh:mm:ssZ.
Similarly, why are you outputting a different regional format like mm/dd/yyyy? If you output '05/06/2013' are you 100% confident that everyone in your audience will know you meant May 6 and not June 5? Your output should be unambiguous as well. If you absolutely must format in some regional and ambiguous format, use the string formatting capabilities of your client. For example, C# has .ToString() and .Format() which are much more powerful and efficient in presenting dates with string formats that T-SQL will ever be.
try the following SQL query to achieve the expected result:
SELECT convert(varchar, convert(date, '27-09-2013 16:15:00', 105), 101)
Related
I am using this
CAST(NotifDate as date) between #FromNotifDate AND #ToNotifDate
but NotifDate is saved as varchar in table but FromNotifDate AND ToNotifDate are of Date type.
When I pass these parameters 08/06/2014 and 20/04/2020 09:40:17 it doesn't work and throws error i.e.
Conversion failed when converting date and/or time from character string.
but if I pass 08/06/2014 and 10/04/2020 09:40:17 it works.
Your current database locale settings are probably set to en-US or another where the date format is MM/dd/yyyy.
That makes 08/06/2014 and 10/04/2014 valid dates (but they are 6th of August and 4th of October, not 8th of June and 10th of April!), but not 20/04/2020.
To use a different date format, you can use CONVERT, with the proper style code (I believe it's 103 for dd/MM/yyyy (see documentation)
So, this should work for you : CONVERT(date, NotifDate, 103)
Note that, as a general recommendation, it would be beneficial that you input NotifDate as a proper SQL Date in your DB in the first place, if possible, to avoid having to do conversion like this in your queries.
Also, there the unambiguous and international standard ISO-8601 format yyyy-MM-dd which should be always parsed correctly by CAST, I recommend using it over any localized format where you can in your code infrastructure.
System having default date format is "MM/dd/yyyy" so while you set "10/04/2020 09:40:17" value so system throm an Error- out of range Error,
-- The conversion of a varchar data type
-- to a datetime data type resulted in an out-of-range value.
select cast('20/04/2020 09:40:17' as datetime)
-- get the current session date_format
select date_format
from sys.dm_exec_sessions
where session_id = ##spid
-- set the dateformat for the current session
set dateformat dmy
-- this should work
select cast('20/04/2020 09:40:17' as datetime)
I can't make out from the documentation why SQL Server parses a text in a format other than the specified style.
Regardless of whether I provide text in the expected format:
SELECT CONVERT(DATETIME, N'20150601', 112)
or incorrect format (for style 113):
SELECT CONVERT(DATETIME, N'20150601', 113)
The results are the same: 2015-06-01 00:00:00.000 I would expect the latter to fail to convert the date (correctly).
What rules does it employ when trying to convert a VARCHAR to DATETIME? I.e. why does the latter (incorrect format style) still correctly parse the date?
EDIT: It seems I've not been clear enough. Style 113 should expect dd mon yyyy hh:mi:ss:mmm(24h) but it happily converts values in the format yyyymmdd for some reason.
Because the date is in a canonical format ie(20150101). The database engine falls over it implicitly. This is a compatibility feature.
If you swapped these around to UK or US date formats, you would receive conversion errors, because they cannot be implicitly converted.
EDIT: You could actually tell it to convert it to a pig, and it would still implicitly convert it to date time:
select convert(datetime,'20150425',99999999)
select convert(datetime,'20150425',100)
select convert(datetime,'20150425',113)
select convert(datetime,'20150425',010)
select convert(datetime,'20150425',8008135)
select convert(datetime,'20150425',000)
And proof of concept that this is a compatibility feature:
select convert(datetime2,'20150425',99999999)
Although you can still implicitly convert datetime2 objects, but the style must be in the scope of the conversion chart.
Reason why is the date N'20150601' converted to valid datetime is because of fact that literal N'20150601' is universal notation of datetime in SQL Server. That means, if you state datetime value in format N'yyyymmdd', SQL Server know that it is universal datetime format and know how to read it, in which order.
You should convert to varchar type in order to apply those formats:
SELECT CONVERT(varchar(100), CAST('20150601' as date), 113)
OK, you are converting datetime to datetime. What did you expect? In order to apply formats you should convert to varchar and you have to have date or time type as second parameter.
I currently have a challenge of storing a DateTime value in a NVarChar field so that it's culture independent.
I've read that you can convert the value to an int by using CONVERT(int, GETDATE(), 112) which should make it culture independent but the former statement doesn't store the time.
What is the industry standard of storing a DateTime as culture independent?
EDIT
Please note that I can't use DateTime in my scenario. It must be NVarChar.
EDIT 2
Alright, found the answer to my own question.
To convert a DateTime to it's binary(8) raw format:
convert(binary(8), GETDATE())
I then store the value in a VARCHAR field as follows:
CONVERT(VARCHAR(MAX), convert(binary(8), GETDATE()), 2)
To retrieve it back from the varchar field and convert it to DateTime:
CONVERT(DateTime,CONVERT(binary(8), [TextField], 2))
As var as I'm concerned, this will store a DateTime as culture independent.
EDIT 3
It seems like user Kaf has the best solution. I will rather use format 126 to convert it to text and then back to DateTime from text.
Thanks everyone and sorry for the confusion.
If you CANNOT store date as Datetime, you can use style 126 which gives ISO8601 format (yyyy-mm-ddThh:mi:ss.mmm (no spaces)). I think it is culture independent.
Fiddle demo
select convert(nvarchar(50),getdate(),126)
Best thing is to store Date as a DateTime/Date type.
You should use DATETIME or DATETIME2 data type to store date and time values. They are stored in binary format in the database and are culture independent.
You can read more on MSDN here: http://msdn.microsoft.com/en-us/library/ms187819(v=sql.100).aspx
More on how SQL Server stores the datetime values: "It uses 8 bytes to store a datetime value—the first 4 for the date and the second 4 for the time." (from: http://sqlmag.com/sql-server/solving-datetime-mystery)
I do not get this idea to store a date in a varchar field so that it is 'culture independant'. dateTime data type is culture independant. What is culture dependent is the way date values are displayed:
MM/dd/YYYY
dd/MM/YYYY
YYYY-MM-DD
etc
But, if the display changes, the underlying value itself is still the same ... and this is why you can easily 'convert' dates from one format to another....
So, for the sake of simplicity, I do strongly advise you to switch to a culture-independant, datetime field. Otherwise any further use of this field's content (calculation, display, print out, etc) will be a real PITA ...
I have date field in the database in the format 2012-03-17 19:50:08.023.
I want to create a select query which gives me the data collected in the March month.
But I am not able to achieve this.
I am trying following query.
select * from OrderHeader where
Convert(varchar,UploadDt,103) between '01/03/2013' and '31/03/2013'
and DistUserUniqueID like '6361%'
This query gives me data for all the dates.
select * from OrderHeader where
UploadDt between '01/03/2013' and '31/03/2013' and DistUserUniqueID like '6361%'
This query gives me the error as Msg 242, Level 16, State 3, Line 1
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
Please help me resolve this.
Thanks in advance
The first query returns all dates because you are converting your column to a string. Not sure why you are doing this. So when you say BETWEEN '01/anything' AND '31/anything', when you consider it is now just a string, that is going to match all "dates" in the column, regardless of month and year, since your WHERE clause will cover every single day possible (well, with the exception of the 31st of months other than March, and the first day in January and February - so not all the data but a very large percentage). '15/11/2026', for example, is BETWEEN '01\03\2013' AND '31/03/2013'.
Think about that for a second. You have datetime data in your database, and you want to convert it to a string before you query it. Would you also convert salary to a string before comparing it? If so, the person making $70,000 will look like they are making more than the person making $690,000, since character-based sorting starts at the first character and doesn't consider length.
The second query fails because you are using a regional, ambiguous format for your dates. You may like dd/mm/yyyy but clearly your server is based on US English formatting where mm/dd/yyyy is expected.
The solution is to use a proper, unambiguous format, such as YYYYMMDD.
BETWEEN '20130301' AND '20130313'
However you shouldn't use BETWEEN - since this is a DATETIME column you should be using:
WHERE UploadDt >= '20130301'
AND UploadDt < '20130401'
(Otherwise you will miss any data from 2013-03-31 00:00:00.001 through 2013-03-31 23:59:59.997.)
If you really like BETWEEN then on 2008+ (you didn't tell us your version) you can use:
WHERE CONVERT(DATE, UploadDt) BETWEEN '20130301' AND '20130331'
More date-related tips here:
Dating Responsibly
Finally, when converting to VARCHAR (or any variable-length data types), always specify a length.
Rewrite the query as
select * from OrderHeader where
UploadDt between '01/03/2013' and '01/04/2013'
and DistUserUniqueID like '6361%'
or
select * from OrderHeader where
UploadDt between Convert(datetime,'01/03/2013', 103) and Convert(datetime,'01/04/2013',103)
and DistUserUniqueID like '6361%'
I have been given a specification that requires the ISO 8601 date format, does any one know the conversion codes or a way of getting these 2 examples:
ISO 8601 Extended Date 2000-01-14T13:42Z
ISO 8601 Basic Date 20090123T105321Z
When dealing with dates in SQL Server, the ISO-8601 format is probably the best way to go, since it just works regardless of your language and culture settings.
In order to INSERT data into a SQL Server table, you don't need any conversion codes or anything at all - just specify your dates as literal strings
INSERT INTO MyTable(DateColumn) VALUES('20090430 12:34:56.790')
and you're done.
If you need to convert a date column to ISO-8601 format on SELECT, you can use conversion code 126 or 127 (with timezone information) to achieve the ISO format.
SELECT CONVERT(VARCHAR(33), DateColumn, 126) FROM MyTable
should give you:
2009-04-30T12:34:56.790
This
SELECT CONVERT(NVARCHAR(30), GETDATE(), 126)
will produce this
2009-05-01T14:18:12.430
And some more detail on this can be found at MSDN.
If you just need to output the date in ISO8601 format including the trailing Z and you are on at least SQL Server 2012, then you may use FORMAT:
SELECT FORMAT(GetUtcDate(),'yyyy-MM-ddTHH:mm:ssZ')
This will give you something like:
2016-02-18T21:34:14Z
Just as #Pxtl points out in a comment FORMAT may have performance implications, a cost that has to be considered compared to any flexibility it brings.
Gosh, NO!!! You're asking for a world of hurt if you store formatted dates in SQL Server. Always store your dates and times and one of the SQL Server "date/time" datatypes (DATETIME, DATE, TIME, DATETIME2, whatever). Let the front end code resolve the method of display and only store formatted dates when you're building a staging table to build a file from. If you absolutely must display ISO date/time formats from SQL Server, only do it at display time. I can't emphasize enough... do NOT store formatted dates/times in SQL Server.
{Edit}. The reasons for this are many but the most obvious are that, even with a nice ISO format (which is sortable), all future date calculations and searches (search for all rows in a given month, for example) will require at least an implicit conversion (which takes extra time) and if the stored formatted date isn't the format that you currently need, you'll need to first convert it to a date and then to the format you want.
The same holds true for front end code. If you store a formatted date (which is text), it requires the same gyrations to display the local date format defined either by windows or the app.
My recommendation is to always store the date/time as a DATETIME or other temporal datatype and only format the date at display time.
You technically have two options when speaking of ISO dates.
In general, if you're filtering specifically on Date values alone OR looking to persist date in a neutral fashion. Microsoft recommends using the language neutral format of ymd or y-m-d. Which are both valid ISO formats.
Note that the form '2007-02-12' is considered language-neutral only
for the data types DATE, DATETIME2, and DATETIMEOFFSET.
Because of this, your safest bet is to persist/filter based on the always netural ymd format.
The code:
select convert(char(10), getdate(), 126) -- ISO YYYY-MM-DD
select convert(char(8), getdate(), 112) -- ISO YYYYMMDD (safest)
For ISO 8601 format for Datetime & Datetime2, below is the recommendation from SQL Server. It does not support basic ISO 8601 format for datetime(yyyyMMddThhmmss).
DateTime
YYYY-MM-DDThh:mm:ss[.mmm]
YYYYMMDD[ hh:mm:ss[.mmm]]
Examples:
2004-05-23T14:25:10
2004-05-23T14:25:10.487
Datetime2
YYYY-MM-DDThh:mm:ss[.nnnnnnn]
YYYY-MM-DDThh:mm:ss[.nnnnnnn]
Examples:
2004-05-23T14:25:10
2004-05-23T14:25:10.8849926
You can convert them using 126 option
--Datetime
DECLARE #table Table(ExtendedDate DATETIME, BasicDate Datetime)
DECLARE #ExtendedDate VARCHAR(30) = '2020-07-01T08:39:17' , #BasicDate VARCHAR(30) = '2009-01-23T10:53:21.000'
INSERT INTO #table(ExtendedDate, BasicDate)
SELECT convert(datetime,#ExtendedDate,126) ,convert(datetime,#BasicDate,126)
SELECT * FROM #table
go
-- Datetime2
DECLARE #table Table(ExtendedDate DATETIME2, BasicDate Datetime2)
DECLARE #ExtendedDate VARCHAR(30) = '2000-01-14T13:42:00.0000000' , #BasicDate VARCHAR(30) = '2009-01-23T10:53:21.0000000'
INSERT INTO #table(ExtendedDate, BasicDate)
SELECT convert(datetime2,#ExtendedDate,126) ,convert(datetime2,#BasicDate,126)
SELECT * FROM #table
go
Datetime
+-------------------------+-------------------------+
| ExtendedDate | BasicDate |
+-------------------------+-------------------------+
| 2020-07-01 08:39:17.000 | 2009-01-23 10:53:21.000 |
+-------------------------+-------------------------+
Datetime2
+-----------------------------+-----------------------------+
| ExtendedDate | BasicDate |
+-----------------------------+-----------------------------+
| 2000-01-14 13:42:00.0000000 | 2009-01-23 10:53:21.0000000 |
+-----------------------------+-----------------------------+
this is very old question, but since I came here while searching worth putting my answer.
SELECT DATEPART(ISO_WEEK,'2020-11-13') AS ISO_8601_WeekNr