SQL Server date formatting from string - sql

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'

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 procedure throws error if I pass it date i.e. 20/04/2020?

I am using this
CAST(NotifDate as date) between #FromNotifDate AND #ToNotifDate
but NotifDate is saved as varchar in table but FromNotifDate AND ToNotifDate are of Date type.
When I pass these parameters 08/06/2014 and 20/04/2020 09:40:17 it doesn't work and throws error i.e.
Conversion failed when converting date and/or time from character string.
but if I pass 08/06/2014 and 10/04/2020 09:40:17 it works.
Your current database locale settings are probably set to en-US or another where the date format is MM/dd/yyyy.
That makes 08/06/2014 and 10/04/2014 valid dates (but they are 6th of August and 4th of October, not 8th of June and 10th of April!), but not 20/04/2020.
To use a different date format, you can use CONVERT, with the proper style code (I believe it's 103 for dd/MM/yyyy (see documentation)
So, this should work for you : CONVERT(date, NotifDate, 103)
Note that, as a general recommendation, it would be beneficial that you input NotifDate as a proper SQL Date in your DB in the first place, if possible, to avoid having to do conversion like this in your queries.
Also, there the unambiguous and international standard ISO-8601 format yyyy-MM-dd which should be always parsed correctly by CAST, I recommend using it over any localized format where you can in your code infrastructure.
System having default date format is "MM/dd/yyyy" so while you set "10/04/2020 09:40:17" value so system throm an Error- out of range Error,
-- The conversion of a varchar data type
-- to a datetime data type resulted in an out-of-range value.
select cast('20/04/2020 09:40:17' as datetime)
-- get the current session date_format
select date_format
from sys.dm_exec_sessions
where session_id = ##spid
-- set the dateformat for the current session
set dateformat dmy
-- this should work
select cast('20/04/2020 09:40:17' as datetime)

sql datetime queries

I have tables with this type of datetime: 2010-09-16 00:32:41.960' CreatedDate column.
I need to perform a query ... where [CreatedDate] >= '2010-09-16 00:32:41.960'
but that just gives me
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
What is the correct syntax, it's been a while since I've done SQL the last time.
Thanks in advance.
Use an unambiguous datetime format so SQL Server doesn't have to guess how to convert it:
where [CreatedDate] >= '2010-09-16T00:32:41.960'
It's a shame that, depending on your regional settings, it may interpret the form with a space separator (rather than T) as YYYY-DD-MM hh:mm:ss. Which gives an out of range month with your example (and wrong results for dates early in the month, except when day=month)
I'd normally list the safe formats as:
YYYYMMDD
YYYY-MM-DD'T'hh:mm:ss
YYYY-MM-DD'T'hh:mm:ss.mil
There are some other formats that are now safe if converting to datetime2 or date, but I can't remember them, and the above usually suffice.
Another alternative would be to run a set dateformat statement before using these date literals:
set dateformat mdy
select MONTH('2010-09-16 00:32:41.960')
Gives 9 as the result, whereas what you're experiencing can be reproduced with:
set dateformat dmy
select MONTH('2010-09-16 00:32:41.960')
Try:
where [CreatedDate] >= CONVERT(datetime,'2010-09-16 00:32:41.960');

SQL Server date format MM/DD/YYYY

How do I check if a date string is in the MM/DD/YYYY format in SQL Server?
SET DATEFORMAT MDY;
SELECT CASE WHEN ISDATE(#string) = 1
AND #string LIKE '[0-1][0-9]/[0-3][0-9]/[1-2][0-9][0-9][0-9]'
THEN 1 ELSE 0 END;
If the result is 1, it's a valid date, but there's no guarantee that it's the date the user meant. If they enter:
06/07/2012
There is no way to know if they meant June 7 or July 6. Your best bet is to make users pick dates from drop-downs or calendar controls, which allows you to control the format and avoid any needless interpretation. Your application layer can use strongly typed variables / parameters and insert into properly typed columns.
If you're after the SQL Server dateformat to see whether it's MDY then use:
dbcc useroptions
And have a look at the dateformat Set Option
you convert date to datestring in this format MM/DD/YYYY using CONVERT function
select convert(varchar(10),getdate(),101)
The output will be as of Sept 8th 2012
09/08/2012
There is no need to validate, other then checking the date field is null or not
You have to do it outside the database. A database stores datetime internally in its own format. I dont think you can read what format the date is stored in. You can read it which ever way you like, for example dd/mm/yyyy or yyyy/mm/dd etc.
What you can do is check this value outside the database for any date field. You can use regular expression for that. But that will be outside the database.

Dateformat oddity in SQL SELECT

I have a table which has a DATETIME column called dtInsertDate.
The value in this column is '2012-08-10 22:48:41.047'. I know that this date is 10th August 2012.
I want to run the following SELECT statement to retrieve this row:
select *
from myTable
where dtinsertdate = '2012-08-10 22:48:41.047'
The puzzling thing is, if I run this SELECT when the option dateformat is mdy, it finds that row.
If I run it on another copy of the database when the option dateformat is dmy, the SELECT doesn't return anything.
Why is this ?
The reason is that dmy causes your string literal to be interpreted as day first - so that is October 8th instead of August 10th.
The solution is to always use an unambiguous format for date literals (or to use properly typed parameters instead of dealing with translating from a string in the first place).
WHERE dtinsertdate = '20120810 22:48:41.047';
As you've discovered, those dashes in your date can make the actual value be interpreted differently depending on language / dateformat settings.
Another alternative is to keep the dashes but to inject a T instead of a space, e.g.:
WHERE dtinsertdate = '2012-08-10T22:48:41.047';
Your original is more readable, but it's only guaranteed to work if you make the language and dateformat fixed (for example try with SET LANGUAGE FRENCH;). Try this experiment:
SET DATEFORMAT DMY;
DECLARE #d DATETIME = '2012-08-10 22:48:41.047'
SELECT MONTH(#d);
GO
SET LANGUAGE FRENCH;
DECLARE #d DATETIME = '2012-08-10 22:48:41.047'
SELECT MONTH(#d);
GO
SET DATEFORMAT MDY;
DECLARE #d DATETIME = '2012-08-10 22:48:41.047'
SELECT MONTH(#d);
GO
SET DATEFORMAT MDY;
SET LANGUAGE ENGLISH;
DECLARE #d DATETIME = '2012-08-10 22:48:41.047'
SELECT MONTH(#d);
GO
Sometimes the result is 8, sometimes the result is 10. Now try it again with one of the two formats I suggest above - result is always 8.
I have lots of juicy details worthy of reading here:
Bad habits to kick : mis-handling date / range queries
But for the specific problem you're talking about, always, always, always use one of the following formats for date/time literals, I don't consider any others safe.
For date + time:
YYYY-MM-DDTHH:MM:SS...
YYYYMMDD HH:MM:SS...
For date only:
YYYYMMDD