DATEDIFF working on yyyymmdd format SQL server - sql

Why the DATEDIFF accepts yyyymmdd format ? Isnt it only for yyyy-mm-dd format ?
The function DATEDIFF(datepart, start_date, end_date) is working fine when the dates are in yyyymmdd format e.g.
DATEDIFF(DAY, 20161201, 20161231);
It gives answer 30
and if you do DATEDIFF(DAY, 20161201, 20161231) + 1 -- end date inclusive
It gives 31
Thanks,
Aiden

This can be a bit hard to tease out, but it is explained in the documentation, in the section "Supported String Literal Formats for date".
There are five sections on this (but the last two are API specific). The first section is affected by internationalization settings and has a bunch of different formats.
The second is the ISO 8601 format. I think the hyphenated format conflicts with the very last format in the first table ("yyyy dd mm" without the hyphens).
The final section has this informative line "A six- or eight-digit string is always interpreted as ymd". Hence, 'YYYYMMDD' is always interpreted correctly. Hence, this is the unambiguous format for date/time.
Note: Because the functions you are using expect dates, if the integer works, then it is converted to a date using its string representation. Normally, date constants should be in single quotes.

Actually its the sql server default format of dates but you can format your dates according to your requirements by following the link:
http://www.sql-server-helper.com/sql-server-2012/format-function-vs-convert-function.aspx

Related

sql date format "2019-10-30", "2019/10/30", "10-30-2019" and "10/30/2019"

I think it's no doubt that in sql "2019-10-30" is valid date format, and looks like "2019/10/30" accepted as well.
What about "10-30-2019" and "10/30/2019"?
I tried them in mariaDB and they're wrong format, but somehow I think I did see them in some sql tables. Please help me clarify the date format. Thanks
In MariaDB, the format for dates is yyyy-mm-dd. But MariaDB is quite lax and other formats are accepted; from the documentation:
A DATE string is a string in one of the following formats: 'YYYY-MM-DD' or 'YY-MM-DD'. Note that any punctuation character can be used as delimiter. All delimiters must consist of 1 character. Different delimiters can be used in the same string. Delimiters are optional (but if one delimiter is used, all delimiters must be used).
A DATE literal can also be an integer, in one of the following formats: YYYYMMDD or YYMMDD.
All the following DATE literals are valid, and they all represent the same value:
'19940101'
'940101'
'1994-01-01'
'94/01/01'
'1994-01/01'
'94:01!01'
19940101
940101
So, for the examples that you provided:
2019-10-30 -- ok: default format
2019/10/30 -- ok: format with alternative delimiter
10-30-2019 -- NOT ok
10/30/2019 -- NOT ok
You can translate a string to a date with function str_to_date().
str_to_date('10-30-2019', '%m-%d-%Y')
str_to_date('10/30/2019', '%m/%d/%Y')
What you are really doing is converting from a string representation of a date to an internal date time representation or data type. The format you are referring to is ISO 8601. The ISO date (2019-10-30 with hyphens or parentheses) format is usually the native or default string conversion that most databases use, that's why those formats work even if you don't specify the conversion. If you intend to convert from other formats you probably would need to specify them. Your default representation for your local settings might work too, but that depends on the specific database.

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)

Multiple date format conversion to single format

I have a column which saves date in a varchar format. I can't change it because it is a part of the existing system. I need to convert this to datetime because I need to apply the datediff function.
The problem is that the dates are in several different formats.
Example:
14/09/2013 dd/mm/yy
20-06-2014 dd-mm-yy
1/29/2013 mm/dd/yy
2013-05-30-15.10.04.812055
8/3/2012 4:22:16 PM dd/mm/yy or mm/dd/yy can't make out the difference
I thought of switching dd and mm but that will be confusing to identify especially with the 1st 3rd and last case. When I convert as is, it gives me an out of range error. How do I fix this?
I am currently using SQL Server 2008

SQL - Comparing between Dates in WHERE Statement not work correctly in Access DB

I am trying to compare between two Dates in my SQL statement. The date format I use in my DataBase is DD/MM/YYYY.
When I write the following sql:
SELECT * FROM [MyTableName]
WHERE #03/10/2014# >= #02/11/2014#;
The result of the WHERE statement is True - (Not Good).
According to the format I wanted (DD/MM/YYYY) it should be False, But in the SQL Statement it appears in a MM/DD/YYYY format.
The same problem was appeared when I used the Now() Function:
WHERE NOW() >= #02/12/2014#;
(Today is the 03/11/2014)
It should be False because 11 < 12 but still the statement is True. (The SQL using the MM/DD/YYYY format).
So I Added a FORMAT function and now it looks like that:
WHERE FORMAT(#03/10/2014#, 'DD/MM/YYYY') >= FORMAT(#02/11/2014#, 'DD/MM/YYYY');
This time the result of the WHERE statement is Flase - (Good!).
So far the Format function looks like a good solution, BUT when trying to reformat the NOW() Date, the problem is appearing again:
This WHERE statement should be True
WHERE FORMAT(NOW(), 'DD/MM/YYYY') = FORMAT(#03/11/2014#, 'DD/MM/YYYY');
But it is False
While this WHERE statement should be False
WHERE FORMAT(NOW(), 'DD/MM/YYYY') = FORMAT(#11/03/2014#, 'DD/MM/YYYY');
And it is True
(Today is the 03/11/2014)
We can see that the Format function not working correctly on the NOW() Date.
Is someone have a solution for that?
Date literals, as delimited with # characters, will usually interpret values of the form NN/NN/NNNN in MM/DD/YYYY format - regardless of your culture settings.
In some cases, such as when the first set of digits is > 12, the environment may choose to interpret the value in DD/MM/YYYY order just to handle the input, but this is non-standard behavior that you should not rely upon.
Specifically, MSDN documentation for the VB Date Data Type says the following:
You must enclose a Date literal within number signs (# #). You must specify the date value in the format M/d/yyyy, for example #5/31/1993#. This requirement is independent of your locale and your computer's date and time format settings.
The reason for this restriction is that the meaning of your code should never change depending on the locale in which your application is running. Suppose you hard-code a Date literal of #3/4/1998# and intend it to mean March 4, 1998. In a locale that uses mm/dd/yyyy, 3/4/1998 compiles as you intend. But suppose you deploy your application in many countries. In a locale that uses dd/mm/yyyy, your hard-coded literal would compile to April 3, 1998. In a locale that uses yyyy/mm/dd, the literal would be invalid (April 1998, 0003) and cause a compiler error.
This is true for VB, as well as VBA and MS Access.
One way to work around this is to not use a date literal. Instead, consider using the DateValue function to parse the string to a date object before querying with it.

SQL Server: Why are dates in ISO-8601 format language dependent?

I need some help understanding date format handling in SQL Server.
If you try the following, it will return a correct result:
SET LANGUAGE English
SELECT CAST('2013-08-15' AS DATETIME)
-- 2013-08-15 00:00:00.000
This, however, will result in a conversion error because apparently SQL Server interprets '8' as the day and '15' as the month:
SET LANGUAGE German
SELECT CAST('2013-08-15' AS DATETIME)
-- Conversion failed when converting date and/or time from character string.
I know that I can use the language-independent (slightly adapted ISO-8601) format YYYYMMDD (without dashes), and it will work in any language.
I don't understand however why YYYY-MM-DD is language dependent, when SQL Books clearly says
"The interpretation depends on the combination of string literal format, ... and default language option settings. ... Some string literal formats are not affected by these settings. ... The ISO 8601 format does not depend on these settings and is an international standard."
http://technet.microsoft.com/en-us/library/ms180878%28v=sql.105%29.aspx
Even looking at the dateformat returned by select * from sys.syslanguages gives no indication - the date format is dmy, so it doesn't match the ISO-8601 format either.
So, the questions are:
Why is the ISO-8601 format language-dependent, even though Books Online says otherwise?
Where can I find the exact format SQL Server uses when parsing ISO-8601 dates?
UPDATE:
Reading further down on http://technet.microsoft.com/en-us/library/ms180878%28v=sql.105%29.aspx#ISO8601Format, it says 'To use the ISO 8601 format, you must specify each element in the format. This includes the T, the colons (:), the + or - , and the periods (.)' (e.g. 2004-05-23T14:25:10).
The table right above (http://technet.microsoft.com/en-us/library/ms180878%28v=sql.105%29.aspx#StringLiteralDateandTimeFormats) says that the ISO 8601 Numeric is not DATEFORMAT dependent, but it also is not Multilanguage. I'm not sure where to find additional information about the Multilanguage part though - e.g., the exact format used in each language.
This related question might help with languages and ISO-8601 date formats.
Why is SQL Server misinterpreting this ISO 8601 format date?
See the article The ultimate guide to the datetime datatypes which was also linked in the answer for more information on the datetime types used by SQL Server.
My guess would be to maintain backwards compatibility. The new datatypes in SQL Server 2008 datetime2 and date is not dependent on SET LANGUAGE or SET DATEFORMAT. Here is a connect item that suggests to change the behaviour for datetime as well.
Hard to answer a question starting with "Why" :-)
This may not answer your question, but for dates there is one string format which will work across ALL locales: 'YYYYMMDD'
Try:
SET LANGUAGE English
SELECT CAST('20130815' AS DATETIME)
SET LANGUAGE German
SELECT CAST('20130815' AS DATETIME)
SET LANGUAGE Japanese
SELECT CAST('20130815' AS DATETIME)
This will give the expected result.