SQL Server nvarchar to date - sql

I'm trying to write a query and convert a nvarchar to a date. I've tried the below but keep receiving an error:
Conversion failed when converting date and/or time from character string.
cast(columnName as DATE) as castDate
convert(Date, columnName, 23) as convertDate
(nvarchar(max),null)
2021-12-30 02:22:24 UTC
Desired output:
2021-12-30

Date and time data types don't support 3 letter abbreviations for timezones (such as 'UTC' here). As you only need to date, then I would suggest you simply take the 10 left most characters and then CONVERT/CAST the value. I use TRY_CONVERT here, as due to the decision to use nvarchar for the data type (not even touching on the fact that it's MAX in length) you could have bad dates:
TRY_CONVERT(date,LEFT(YourColumn,10))
Fortunately, yyyy-MM-dd is an unambiguous format for the date data type.
I do, however, strongly suggest you fix your design. nvarchar is not an appropriate data type for a date and time value, and certainly a MAX length value (suggesting that the value of the date is likely to be more than 4,000 characters in length) is completely wrong. Most likely you should be using a datetimeoffset here (or maybe just as datetime2 if all your values are UTC).

Related

Convert string to datetime in SQL, when Z and T literals are involved [duplicate]

This question already has answers here:
SQL Server : DATEADD() not working beyond milliseconds when using a string value
(2 answers)
Closed 1 year ago.
A date is stored as string in the database:
2021-12-15T14:18:22.6496978Z
I try to convert it to datetime:
CONVERT(DATETIME, '2021-12-15T14:18:22.6496978Z', 127)
using 127 which refers to yyyy-mm-ddThh:mi:ss.mmmZ, which I believe is the right style for the input date. But I am getting
Conversion failed when converting date and/or time from character string.
Any ideas why?
DATETIME and SMALLDATE are legacy types(as in replaced-15-years-ago, don't-use legacy) that have a lot of quirks and limited precision. For example, datetime is only accurate to 0, 3 or 7 milliseconds. The value you tried to parse can't be converted to a datetime without losing precision.
The docs warn strongly against using this type, with a big pink warning at the top of the DATETIME page:
Use the time, date, datetime2 and datetimeoffset data types for new work. These types align with the SQL Standard. They are more portable. time, datetime2 and datetimeoffset provide more seconds precision. datetimeoffset provides time zone support for globally deployed applications.
In this case you need the datetime2 or datetimeoffset types introduced in 2005. Both types allow specifying a precision.
To preserve the timezone offset, use datetimeoffset.
select CONVERT(datetimeoffset, '2021-12-15T14:18:22.6496978Z', 127)
----
2021-12-15 14:18:22.6496978 +00:00
To remove the offset, use datetime2. The result will have no assumed offset so you should take care to always treat it as UTC:
select CONVERT(datetimeoffset, '2021-12-15T14:18:22.6496978Z', 127)
----
2021-12-15 14:18:22.6496978
In both cases you can specify the desired precision. For example, datetime2(0) will truncate fractional seconds:
select CONVERT(datetime2(0), '2021-12-15T14:18:22.6496978Z', 127)
---
2021-12-15 14:18:23

String to datetime conversion in sql server

Is it possible to convert 'OCT-20' to '2020/10/01' in sql server. I tried the following cases without any luck.
select convert(date, 'OCT-20',103)
----Conversion failed when converting date and/or time from character string.
alter table MyTable alter column [period] date
----Conversion failed when converting date and/or time from character string.
I am using sql server 2016.
If we assume that the value is always in the format MMM-yy then you could do this:
SELECT CONVERT(date,'01-' + StringDate,106)
FROM dbo.YourTable;
Of course, this has 2 flaws.
The date uses a 2 digit year, so SQL Server could assume the wrong century
It'll only work if the LOGIN is using an English based language, otherwise it'll fail.
The real solution is to fix your design; never store date (and time) values in a varchar, and when ever you do use a varchar for a date (such as a literal in a WHERE) use an unambiguous format such as yyyyMMdd or yyyy-MM-ddThh:mm:ss.nnnnnnn.

Why sysdate-'dd-mm-yyy' is not valid in-spite of internal conversion being possible?

'dd-mm-yy' being NLS_DATE_FORMAT it is implicitly converted to Date data type during comparison, insertion but why is not converted during a arithmetic operation.
sysdate>'01-01-17' //is valid
sysdate-'01-01-17' //is in valid
First I assumed the operators(+,-,..) are only for numeric data type. Later I got to know these operators are used even in Date Arithmetic and even operands with Datedata type are also valid.
"During arithmetic operations on and comparisons between character and noncharacter datatypes, Oracle converts from any character datatype to a numeric, date, or rowid, as appropriate" -
doc
Using to_date solves the issue. I am looking for the reason why it is not implicitly converted.
Forget implicit conversion. Just express your dates using explicit date literals:
sysdate > date '2017-01-01'
sysdate - date '2017-01-01'
The code is clearer and less ambiguous as well.
As to why Oracle doesn't do implicit conversion in the second case. Oracle doesn't know what type to expect. The second operand could be either a date or a number, so it doesn't know how to convert the string. In the first case, the comparison should be to a date.
Adding more detail on Gordon Lindoff's answer with an example.
During sysdate>'010117' as your comparing with a date '010117' surely should be date and is implicitly converted. Same going during insert.
But during sysdate-'010117' the system has the possibilities of converting it Number or Date, and it chooses to convert into Number. So 'dd-mm-yy' format is tried to convert into Number in this context.

Why does SQL Server convert VARCHAR to DATETIME using an invalid style?

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.

SQL Server DateTime2(0) vs Date

What are the implications of using SQL Server's DateTime2 with a precision of 0 to represent a date rather than the built in Date field.
In either case, my concern is to prevent accidental time entries, but are there storage or performance considerations I should take note of?
DateTime2(0) will store datetime with no decimal values i.e YYYY-MM-DD hh:mm:ss
SELECT CONVERT(DateTime2(0) , GETDATE())
RESULT: 2015-04-06 20:47:17
Storing data just as dates will only store dates i.e YYYY-MM-DD without any time values.
SELECT CONVERT(Date , GETDATE())
RESULT: 2015-04-06
If you are only interested in dates then use DATE data type.
DATETIME2 will use 6 bytes for precisions less than 3 and DATE will use 3 bytes.
Date is half the size of DATETIME(0) hence it will also perform better since sql server will process less data and will save disk space as well.
It won't work. According to MSDN the minimum size of Datetime2 is six bytes and will contain hh:mm:ss so it can, and will, contain a time component (default of midnight). As other responders have noted you must use a date type to guarantee that not time portion is saved and will occupy three bytes.
https://technet.microsoft.com/en-us/library/bb677335%28v=sql.105%29.aspx
Just a reminder which I ran into myself when I converted a couple of DATETIME2(0) columns to DATE to make sure it aligned better with the value in the column (date only).
When using DATE you cannot use things like SELECT MyDate + 1 FROM.. or WHERE MyDate>0 while when using DATETIME2 you can, at least not in MS-SQL. Ofcourse IMHO it doesn't make any sense why DATETIME2 will allow you to do it and DATE not.