retrieve date format from machine settings - sql

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.

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

SQL Table datetime column format

I tried googling to get an answer but in vain. Below is my requirement
User has an option to insert data into a table which has export_date as datetime
When they execute insert statements, I want to ensure that they have keyed in date in "dd-MM-yyyy hh:mm:ss" format. If not, don't allow insert queries to run.
Or allow the user to enter date in any format like dd-MM-yyyy or dd/MM/yyyy but internally convert it into the required format "dd-MM-yyyy hh:mm:ss" and store
Can someone help/guide me?
You can use Set DateFormat
Example
Used data type of date for illustration, but clearly you can use datetime
Set DateFormat DMY
Select try_convert(date,'15/08/2017') -- Returns 2017-08-15
Set DateFormat MDY
Select try_convert(date,'15/08/2017') -- Returns NULL
Set DateFormat YMD
Select try_convert(date,'15/08/2017') -- Returns NULL
You will likely run into issues if you want the user to input the date in the "dd-MM-YYYY" format since if the user inputs in the mm-dd-yyyy format, you'll get different results. "YYYMMDD" is a generic format that SQL Server will always interpret properly.
Once you get the date from the user, you can convert it using the particular format that you want. The following will convert the date to the ISO8601 format:
SELECT
GETDATE() AS UnconvertedDateTime,
CONVERT(nvarchar(30), GETDATE(), 126) AS UsingConvertTo_ISO8601 ;
GO
For more information on the specific date formats, I'd recommend checking out Microsoft's Convert Functions.

Default Culture Used by SQL Server For Parsing

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.

Datetime interpretation issue

I have the following data:
StartDate FinishDate Details
09/10/2013 11/10/2013 xxx
14/10/2013 13/10/2014 Taking a year off
Whilst editing this data I which to check the date ranges do not overlap.
I am running an SQL query from access via ado to do this; I am putting the dates entered into database format (ie 'mm/dd/yyyy'); This is the query I've got:
SELECT Count(*)
FROM MarkerAbsence
WHERE PerID = 718 AND
('10/09/2013' BETWEEN StartDate AND FinishDate OR
'10/11/2013' BETWEEN StartDate AND FinishDate)
If the data is valid, it should return zero records; however it doesnt it returns 1 (being the second listed record above) and therefore seems to be interpreting '10/11/2013' as dd/mm/yyyy instead of mm/dd/yyyy.
Yet if I do this in SMO:
DECLARE #datevar datetime2 = '31/12/2008';
SELECT #datevar;
I get:
Msg 241, Level 16, State 1, Line 1
Conversion failed when converting date and/or time from character string.
While
DECLARE #datevar datetime2 = '12/31/2008';
SELECT #datevar;
returns
2008-12-31 00:00:00.0000000
So why am I having this problem and how do I fix it?
If you're running a query using MS Access, you need to delimit dates with # symbols, i.e.: #12/31/2008#. If this won't work for whatever reason, it is best to use string dates in the 'yyyy-mm-dd' format, as it will be recognized and is unambiguous.
You're probably getting this problem as MS is a US company, and the US uses mm/dd/yyyy format, so MS has defaulted much of their older software to treat dates as being in this format if at all possible, whereas you're probably in a country that uses - and have your PC's locality set to use - dd/mm/yyy format. Since not all of MS' software follows this rule, you have this problem.
The solution is to use a string date format that is unambiguous, such as: yyyy-mm-dd, mmm/dd/yyyy, or dd/mmm/yyyy (where mmm returns a three-letter month such as Dec).
You are using dd/mm/yyyy formats for your date strings. By default, without an explicit conversion, SQL is expecting date strings in the mm/dd/yyyy or yyyy-mm-dd format. So either change your strings to match one of these formats or do this:
SELECT Count(*)
FROM MarkerAbsence
WHERE PerID = 718 AND
(CONVERT(DATETIME, '10/09/2013', 103) BETWEEN StartDate AND FinishDate OR
CONVERT(DATETIME, '10/11/2013', 103) BETWEEN StartDate AND FinishDate)

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'