Default Culture Used by SQL Server For Parsing - sql

When I run the following statement:
SELECT CAST ('12/08/1988' AS DATE) AS BIRTHDAY
I get the 1988-12-08, not 1988-08-12 in ISO 8601 format. How does SQL Server decide which format to apply for parsing? I know the best practices, I'm just interested in where does it take it and how it can be changed?

First.. Format for parsing dates is based on an environment language currently set in the active session. You can see the current language with SELECT ##LANGUAGE and you can change it using SET LANGUAGE command.
Next you can override the format of current language by setting your own date format with SET DATEFORMAT. However, mind that if you change language again, it overrides the format settings.
Here are few examples on how different settings behave and affect your CAST query:
SET LANGUAGE Italian
SELECT ##LANGUAGE
, CAST ('12/08/1988' AS DATE) AS BIRTHDAY
, DATENAME(month,CAST ('12/08/1988' AS DATE)) AS MonthName;
SET LANGUAGE English
SELECT ##LANGUAGE
, CAST ('12/08/1988' AS DATE) AS BIRTHDAY
, DATENAME(month,CAST ('12/08/1988' AS DATE)) AS MonthName;
SET DATEFORMAT DMY
SELECT ##LANGUAGE
, CAST ('12/08/1988' AS DATE) AS BIRTHDAY
, DATENAME(month,CAST ('12/08/1988' AS DATE)) AS MonthName;
Default language setting for each new query is set on login level. You can change it by finding in Object Explorer on server->Logins->YourLogin->Properties->Default Language or with ALTER LOGIN command
Further, there is also a default language on server, which affects default choice for newly created logins.
More about that you can find in this question:
How to change default language for SQL Server?
At the end, like others said, you should avoid confusion by using CONVERT with style, ISO format and appropriate data types.
My tips:
If you want to convert string to date in adhoc queries (like in example), always use ISO format and there is no need to worry about format and not even a need to convert:
SELECT * FROM Table WHERE DateColumn = '20170325'
If you want to convert date to string (for display) use CONVERT with desired style:
SELECT CONVERT(NVARCHAR(30), DateColumn, 104) FROM Table

SQL Server doesn't have a "culture", it will just always parse a value in that format as mm/dd/yyyy (i.e. US format). you can control it to some degree using DATEFORMAT, for example:
SET DATEFORMAT mdy
However, these are fairly basic formats and you really should avoid relying on them.
If you want to change it, you should use the CONVERT function, or the newer PARSE. For example, to specify British format:
SELECT CONVERT(DATE, '12/08/1988', 103)
Or:
SELECT PARSE('12/08/1988' AS DATETIME USING 'en-GB')

Doing this will always be more reliable, regardless of date formats:
SELECT CAST ('1988-08-12' AS DATE) AS BIRTHDAY
As you're not specifying the format, it will use default date format on your SQL instance, which looks like English US.

Related

SQL query is using YYYY-DD-MM format, when table is YYYY-MM-DD

If I run the query:
select startdate, count(*)
from tablename
where startdate > '2020-04-06'
It only returns value where the startdate is after 4th June 2020. However the dates in the table are in the format YYYY-MM-DD HH:mm:ss.sss.
If I run a getdate() or sysdatetime() it returns 2020-06-16 14:29:29.157 in the correct format.
So why is the query using YYYY-DD-MM? And how do I get it to change by default?
P.S. I'm aware that I could use CONVERT or FORMAT in the query, but as all dates will be in the YYYY-MM-DD format I'd like that to be the default, and not have to write extra code each time.
EDIT: I'm using Microsoft SQL Server Management Studio
EDIT2: I checked with a colleague and the same thing happens to them.
That depends on various settings. You can get around this by removing the hyphens:
startdate > '20200406'
In SQL Server, this format is always unambiguous, YYYYMMDD. I prefer the version with the hyphens, because it is more standard. But if you are dealing with this as an issue I would suggest using the SQL Server unambiguous format.
You can handle it in two ways:
At the session level. you can set format and issue query
Use ISO 8601 format (Recommended)
DECLARE #table table(a datetime)
INSERT INTO #table values('2020-04-06')
SELECT * FROM #table WHERE A = '2020-04-06' -- ISO 8601
set dateformat ymd
SELECT * FROM #table WHERE A = '2020-04-06' -- Format change

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.

Change the Display date format without using CONVERT

dbcc useroptions
shows the date format
later i changed format using
set dateformat dmy
even though i changed the format the date is being display in the the format of yyyymmdd
how to change the display format without using CONVERT
Since, you didn't mentioned that we can't use CAST, Would the following work for you?
select CAST(getdate() as nvarchar(30))
I know i am not being too fair, but that's all i could do.
you can do something like
SELECT ProductName, Price, FORMAT(Now(),'dd/MM/yyyy') AS PerDate
FROM Products;
SET DATEFORMAT allows you to INSERT/UPDATE dates with different formats without doing any special data conversions.It's not used to get specific date format. The default input format of us english is mdy.If you need to get date in dmy format then you can change the language to Birtish english because the default date format is dmy
SET LANGUAGE 'british english'
Note:Changing database will effect on whole server not on individual databases

SQL Server date formatting from string

We've recently migrated our database to a different server and since this I think the date format querying has changed somehow.
Previously we could use the following..
SELECT * FROM table WHERE date > 'YYYY-MM-DD'
However now we have to use..
SELECT * FROM table WHERE date > 'YYYY-DD-MM'
Can someone tell me what I need to change to get back to the previous version?
Try this one -
Query:
SET DATEFORMAT ymd
Read current settings:
DBCC USEROPTIONS
Output:
Set Option Value
-------------------------- -----------------
...
language us_english
dateformat ymd
...
You are right, the date format is different between the servers.
Lots of people fall into the trap of assuming that if you specify a date literal as 'YYYY-MM-DD', it will be interpreted as that regardless of the current date format. This is incorrect. SQL Server sees the 4 digits at the start of the string and correctly deduces that they represent the year. However, it then uses the current date format to tell which way round the month and day are. If you are in the UK, for example, this puts you in an awkward situation because you need a date format of DMY to interpret a date literal like 'DD-MM-YYYY', but a date format of MDY to interpret a date literal like 'YYYY-MM-DD'.
You have several options:
SET DATEFORMAT YMD, and don't let users enter dates any other way.
Use the ODBC date literal syntax {d'YYYY-MM-DD'}. This will be parsed correctly regardless of the current date format. CONVERT(DATE, 'YYYY-MM-DD', 120) has the same effect.
Remove all literal values from your queries and use parameters instead. This is by far the best alternative, and I strongly recommend it.
is you use different formats for the string then you can avoid this behaviour.
There are 2 iso formats that are always specific -- sql server will always parse them in the same way regardless of the server date format setting.
These are:
1) Short form : YYYYMMDD. Example '20120301' -- 1st March 2012
2) Long Form : YYYY-MM-DDTHH:MM:SS.msms'. Example '2012-03-01T12:13:00.000Z' -- 1st March 2012 at 13 minutes past 12 (PM)
In the long form the miliseconds is optional -- this is a perfectly acceptable ISO datetime '2012-03-01T12:13:00Z'
The Z at the end is time zone information. SQL Server doesn't actually require this. (though other products are a bit more exacting)
Try this for example:
DECLARE #foo DATETIME
SET DATEFORMAT DMY
-- this will be the 3rd of january in DMY
SET #foo = '2012-03-01'
SELECT 'DMY: Not ISO', #foo
SET #foo = '20120301'
SELECT 'DMY: ISO', #foo
SET DATEFORMAT MDY
-- this will be the 1st of March in MDY
SET #foo = '2012-03-01'
SELECT 'MDY: not ISO', #foo
SET #foo = '20120301'
SELECT 'MDY: ISO', #foo
When you use text to enter dates you should always try to use one of the two ISO standards. It just makes things much more deterministic.
Short format (SQL Server)
http://msdn.microsoft.com/en-US/library/ms187085(v=sql.90).aspx
ISO 8601 Format (SQL Server)
http://msdn.microsoft.com/en-us/library/ms190977(v=sql.90).aspx
It's a matter of language/culture
Set Language 'us_english'

retrieve date format from machine settings

how do i retrieve the date format of the machine the script is running on
declare #inputdate varchar(25)
declare #datetemp datetime
select #inputdate = '3/13/2012'
select #datetemp = CAST(#inputdate as DATETIME)
select #datetemp
here's the scenario: i have a date string coming in and i need to format a usa date in a customized way (mm/dd/yyyy am/pm) vs the other dates in other parts of the country (which might be dd/mm/yyyy 24:hr)
so i need to find a way to get the machine's date format setting.
I suspect the machine's date format setting is not really what you want. When you run a query on the server, it uses the language setting of the logged in user. There is a way to get the dateformat of the logged in user...
Select DateFormat
From sys.syslanguages
Where name = ##Language
This will return the dateformat. For us_english, it returns 'mdy'.
Relying on the machines regional settings at the SQL Level would be a rather strange way of doing it (especially for server / client scenario as any SQL would get the servers setting). For instance, rather than relying on CAST to convert your string to a date, you should be a little bit more specific by specifying what format the source string is. For example:
DECLARE #inputdate VARCHAR(25)
DECLARE #datetemp DATETIME
SELECT #inputdate = '13/03/2012'
SELECT CONVERT(DATETIME, #inputdate, 103) --### 103 = DD/MM/YYYY input date
SELECT #inputdate = '03/13/2012'
SELECT CONVERT(DATETIME, #inputdate, 110) --### 110 = MM/DD/YYYY input date
Note how two different input dates can be converted to the same day by telling SQL what format the string is in. It would be up to your interface to either restrict the user to a certain date format or determine the regional settings and pass this to SQL & have SQL implement the correct style parameter accordingly.