T-SQL CONVERT fails with providing ISO formatted string + style - sql

I'm getting an error I didn't expect to see when using CONVERT with an ISO formatted string, but only when specifying a style code (I've tried a few, and they all throw the error).
For example, this succeeds and returns the datetime in my local format:
select CONVERT(datetime, '2020-01-15T00:00:00')
But this fails with an error
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value
select CONVERT(datetime, '2020-01-15T00:00:00', 103)
I feel I must be missing something very basic here. Can anyone explain?

103 forces the format for convert().
Otherwise, convert() is somewhat flexible on the format you can provide. It does not just use the default format.
Your format, in fact, is the standard format for date/time values. And so it recognizes that regardless of the local settings. Similarly, a string YYYYMMDD is always recognized as a valid date, regardless of the local settings.

Related

SQL Server doesn't get date format dd-mm-yyyy

I'm trying to INSERT date variable into my SQL server.
The input format I'm trying to insert is: dd-mm-yyyy
And my SQL server column (which defined as type DATE) expect mm-dd-yyyy.
My PC date format is dd-mm-yyyy.
The error msg:
Conversion failed when converting date and/or time from character string.
Questions:
Why is the expected format mm-dd-yyyy and not dd-mm-yyyy?
How can I make the INSERT command work with this or another date format?
Thanks.
The format that your PC uses for dates doesn't matter when passing literal string for dates, the language setting for the LOGIN you are using to connect to SQL Server does. As the value is being interpreted as MM-dd-yyyy this very likely means that your language setting is (American) ENGLISH.
If, therefore, you are the only person that uses that LOGIN you may well want to change the language of your LOGIN to be appropriate for yourself. Most of the European languages, including BRITISH English (because the British don't speak English Microsoft? 😒) use the format dd-MM-yyyy.
Really, however, what you should be doing is using an unambiguous date format, of which there are only 2 in SQL Server, regardless of the language setting and data type. Those 2 formats are yyyyMMdd and yyyy-MM-ddThh:mm:ss.nnnnnnn. If you are always using the newer date and time data types (so not datetime or smalldatetime), then yyyy-MM-dd( hh:mm:ss.nnnnnnn) is also unambiguous, however, as it's language specific for the older data type then I don't normally recommend it's use.
Storage wise, date and time data types don't have a format, so your column isn't "expected" a value in the format MM-dd-yyyy, as it doesn't retain the "format data" that the value was passed in. Again, the only reason why a value like 13-12-2020 is working is because your language setting, which uses mdy for date interpretation.
Two things really,
Firstly, you can control the expected date format for each connection. Before issuing the insert statement, do set dateformat dmy; or set dateformat mdy; as appropriate.
Secondly, it's always advisable to work with dates in the ISO format of YYYYMMDD, so if you insert the data '20210314' it will always be treated correctly.

Specify string date format before casting in a function SQL

I have a scenario to cast string date into date format. But the date string is not in a straight format, so the conversion throws error. So what I tried is
set dateformat dmy
before the casting in sql and it worked without any issue.
But the trouble is I need this to implement in a view or function. But the disappointing part, function or view doesn't support set dateformat with which it says as side effecting operator
So how can I specify the date format of the given string before casting in a function or view?
The third parameter of CONVERT() allows to provide a format type.
Assuming your SET DATEFORMAT DMY I take you've to deal with dates like "1/2/2000", meaning the first of February in 2000.
Try this:
DECLARE #d VARCHAR(100)='1/2/2000';
SELECT CONVERT(DATE,#d,104)
The 104 is the German type with a 4-digit year. If this does not fit your needs, you can follow the link to find a better suiting format.
If you need further help, please provide samples of your actual dates.
Hint: You should always store a value in a column with the appropriate type. Storing dates as strings will make things slow and opens a lot of error sources...
As Damien wrote in his comment to the question, ideally you should not mess around with string representations of datetime in the first place - you should be using proper data types - and since you asked about creating a view, it can only mean that somewhere in your database there's a datetime value stored as a string.
The solution to this situation is to change the way you are storing this value - use DateTime2 for datetime values, Date for date-only values, or Time for time-of-day values.
Further reading - Aaron Bertrand's Bad habits to kick : choosing the wrong data type
Assuming you can't change the database design, read the rest of this answer.
You can't use set dateformat on a view or a function, but you can use convert instead of cast to change the string representation of a datetime value into an actual datetime value, assuming the string representation has one of the supported date formats (there are quite a few of them, so usually it shouldn't be a problem).
If your string representation of the datetime is in a format that is not supported by the built in convert function, you might need to do some extra work in the form of string manipulation to either change it into a supported format, or (in the harder case) separate the string representation to parts and then use datetimefromparts.
If you could provide the actual format you are using in your string representation of the datetime format I can probably edit this answer to show you exactly how to do it.
SELECT CONVERT(varchar(10),CAST('07/01/2018' AS DATE),23)
Result
2018-07-01
Not sure what you mean by, "date string is not in a straight format". Examples will help.
Have you tried parsing, instead of casting?
SELECT
TRY_PARSE(thedate AS datetime) as justParse
,TRY_PARSE(thedate AS datetime USING 'en-US') as parseUS
,TRY_PARSE(thedate AS datetime USING 'en-GB') as parseGB
,try_cast(thedate as date) as tryCast
FROM (values
('07/01/2018')
,('01/07/2018')
,('07 jan 2018')
,('jan 07 2018')
,('Monday, 7 January 2019')
)d(thedate)

SQL Server ignores given format with CONVERT()

I believe this should be a fairly easy task but somehow it fails. I have dates stored in a text-field like dd-mm-yyyy and I'm converting them to DateTime-types using CONVERT(datetime, [MyDateAsTextField], 105). But the output I''m getting is yyyy-dd-mm 00:00:00.000 and I'm not sure why. What am I missing?
You are getting the output as a date/time in the correct format used for output. Dates and times are stored in an internal format. convert() translates values between strings and the internal format.
If you want the output in a different form, you can use convert(varchar(), . . .) to get the format you want.
More importantly, though, you should not store date/time values strings. You should use the built-in types. They offer much more functionality.
Instead of using datatype as datetime use Char(10) or Varchar(10) and the date style like 105 for dd-mm-yy (Italian).
E.g.:
CONVERT(Char(10), getdate(), 105)
Output will be: 20-02-2015

Converting UK format date to datetime

I have a value in SQL that represents a date, but it of type nvarchar. The value of the date is in the format:
dd/mm/yyyy hh:mm
I need to present this column via a view to a CCure 800 database in DATETIME format. I expected to use CAST/CONVERT; however, when using this, the following error is returned:
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 stop storing dates as strings, and especially as Unicode strings. Are you concerned that some future version of our calendar will have umlauts, pound signs, hieroglyphics, or Mandarin instead of numbers?
Store dates as dates. That is what those data types are for. In addition to not having to worry about invalid interpretations, you also get all of the benefits of things like DATEPART and DATEADD, and you don't have to worry about anyone stuffing nonsense into the column (anything from 31/02/2012 to 'I don''t want to enter a real date'...
In the meantime, you just need to use a style number with CONVERT (this won't work reliably with CAST):
SELECT CONVERT(DATETIME, '13/06/2013 09:32', 103);
To make it work with CAST, you could set your LANGUAGE or DATEFORMAT settings accordingly, but you can't do this inside a view, and it makes the code very brittle anyhow IMHO.
SET DATEFORMAT DMY;
SELECT CAST('13/06/2013 09:32' AS DATETIME);
Or
SET LANGUAGE BRITISH;
SELECT CAST('13/06/2013 09:32' AS DATETIME);
By a very wide margin, I prefer the additional control CONVERT gives you, and almost unilaterally change all instances of CAST to CONVERT, even when this control is not needed, for consistency (why use CAST in some cases, and CONVERT when you need it, when you can just use CONVERT always?).
EDIT
To identify the garbage data that has snuck into your table because of a bad data type choice, do this (and then fix the data or, better yet, fix the data type so this doesn't happen again):
SET DATEFORMAT DMY;
SELECT date_column FROM dbo.table_name WHERE ISDATE(date_column) = 0;

how to reformat DateTime data type

I know that it is possible to reformat the DateTime data type of the current date and time by using select convert. However, I havent been able to find a method to reformat an existing column (DateTime data type) to: hh:mm:ss yyyy/mm/dd. Or even better, I would like to reformat it to show time only. I dont want to simply convert to time data type because I am working with a chart that accepts either Date or Date time. But what I really want to display on that specific axis of the chart is time. Is there any way to reformat DateTime to my requirements? Thanks.
SQL Server's convert function can take an optional style argument depending upon the datatype. This is how you can get a datetime converted to a string in a variety of formats. For example, try running:
select convert(varchar(30), getdate(), 108) -- returns hh:mi:ss
You can replace getdate() in this example with a column name as well.
There are many styles available, as shown in the documentation.
Note that you will be returning a varchar, so you may want to sort by the original column's datatype.
You can use SET DATEFORMAT but this will change all DateTime's on your SQL Server. You can do some custom formatting, but it will convert the DateTime into a VarChar, so you won't be able to treat it as a DateTime.
SET DATEFORMAT: http://msdn.microsoft.com/en-us/library/ms189491.aspx
I'm not sure if you will be able to use the format you're asking about, though.