SQL Server conversion issue with datetime - sql

I always use this code for conversion in datetime:
DECLARE #a datetime
SET #a= CONVERT(datetime,'2012-12-28 14:04:43')
print #a
But this does not work anymore! I tried even restarting SQL Server, but the problem remains:
The error in the image is in Italian. In English should be:
The conversion of a char data type to datetime resulted in a datetime
value that is out of range of allowed values​​.

There are many formats supported by SQL Server - see the MSDN Books Online on CAST and CONVERT. Most of those formats are dependant on what settings you have - therefore, these settings might work some times - and sometimes not.
The way to solve this is to use the (slightly adapted) ISO-8601 date format that is supported by SQL Server - this format works always - regardless of your SQL Server language and dateformat settings.
The ISO-8601 format is supported by SQL Server comes in two flavors:
YYYYMMDD for just dates (no time portion); note here: no dashes!, that's very important! YYYY-MM-DD is NOT independent of the dateformat settings in your SQL Server and will NOT work in all situations!
or:
YYYY-MM-DDTHH:MM:SS for dates and times - note here: this format has dashes (but they can be omitted), and a fixed T as delimiter between the date and time portion of your DATETIME.
This is valid for SQL Server 2000 and newer.
If you use SQL Server 2008 or newer and the DATE datatype (only DATE - not DATETIME!), then you can indeed also use the YYYY-MM-DD format and that will work, too, with any settings in your SQL Server.
Don't ask me why this whole topic is so tricky and somewhat confusing - that's just the way it is. But with the YYYYMMDD format, you should be fine for any version of SQL Server and for any language and dateformat setting in your SQL Server.
So in your concrete case - use this:
DECLARE #a datetime
SET #a= CONVERT(datetime, '2012-12-28T14:04:43')
print #a
and this should work on any SQL Server installation, with any language and date format settings.
If you run your original code for US English - it will work just fine:
SET LANGUAGE English
DECLARE #a datetime
SET #a= CONVERT(datetime, '2012-12-28 14:04:43')
print #a
Dec 28 2012 2:04PM
but if you use Italian (or German, or British, or French) as your language, it will fail because the format without the T in the middle of the date/time string is NOT language-independent and not "safe" :
SET LANGUAGE Italian
DECLARE #a datetime
SET #a= CONVERT(datetime, '2012-12-28 14:04:43')
print #a
Msg 242, Level 16, State 3, Line 4
La conversione di un tipo di dati varchar in datetime ha generato un valore non compreso nell'intervallo dei valori consentiti.

You are trying to convert a string to a datetime. Problem is with the date part. Best way is to get the date string into ISO format (yyyymmdd) and then convert. Try this;
DECLARE #a datetime
SET #a= CONVERT(datetime,replace('2012-12-28 14:04:43', '-',''))
print #a

My guess is that the default date time format changed on your computer. Add the conversion specification back in:
SET #a= CONVERT(datetime,'2012-12-28 14:04:43', 121)

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 Query with Dates

Here is the structure of my DB:
CREATE TABLE [dbo].[P](
[O] [nchar](50) NULL,
[C] [datetime] NULL,
[S] [nchar](50) NULL,
[M] [datetime] NULL
) ON [PRIMARY]
GO
I'm really not getting this DateTime malarky with SQL :(
Whenever I run this:
INSERT INTO P (O, C, S, M)
VALUES ('32','17/04/2014 16:50:37','Complete','21/08/2006 22:50:41')
All I get is this error:
The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value.
I have tried cast as datetime and convert using various styles but every time I get the same error.
Can someone please tell me where I am going wrong?
Thanks
There are many string formats for a date supported by SQL Server - see the MSDN Books Online on CAST and CONVERT. Most of those formats are dependent on what settings you have - therefore, these settings might work some times - and sometimes not.
The way to solve this is to use the (slightly adapted) ISO-8601 date format that is supported by SQL Server - this format works always - regardless of your SQL Server language and dateformat settings.
The ISO-8601 format is supported by SQL Server comes in two flavors:
YYYYMMDD for just dates (no time portion); note here: no dashes!, that's very important! YYYY-MM-DD is NOT independent of the dateformat settings in your SQL Server and will NOT work in all situations!
or:
YYYY-MM-DDTHH:MM:SS for dates and times - note here: this format has dashes (but they can be omitted), and a fixed T as delimiter between the date and time portion of your DATETIME.
This is valid for SQL Server 2000 and newer.
If you use SQL Server 2008 or newer and the DATE datatype (only DATE - not DATETIME!), then you can indeed also use the YYYY-MM-DD format and that will work, too, with any settings in your SQL Server.
Don't ask me why this whole topic is so tricky and somewhat confusing - that's just the way it is. But with the YYYYMMDD format, you should be fine for any version of SQL Server and for any language and dateformat setting in your SQL Server.
The recommendation for SQL Server 2008 and newer is to use DATE if you only need the date portion, and DATETIME2(n) when you need both date and time. You should try to start phasing out the DATETIME datatype if ever possible
So in your concrete case, try to use this INSERT:
INSERT INTO P (O, C, S, M)
VALUES ('32', '2014-04-17T16:50:37', 'Complete', '2006-08-21T22:50:41')
(with dashes, and with a "T" delimiter between date and time)
or
INSERT INTO P (O, C, S, M)
VALUES ('32', '20140417 16:50:37', 'Complete', '20060821 22:50:41')
(no dashes, no "T" delimiter between date and time)
By default, SQL server prefers the YYYYMMDD format.
You can override the format to make your query work without using the convert function by doing the following:
SET DATEFORMAT DMY
Note that this setting does not affect the underlying storage format, and only changes the way dates are interpreted as input, by default, for the context of the current connection.
This will work:
CREATE TABLE #test ( D DATETIME )
SET DATEFORMAT DMY
INSERT INTO #test
( D )
VALUES ( '21/12/2001 18:05:56' )
DROP TABLE #test

Why is SQL Server misinterpreting this ISO 8601 format date?

Why is SQL Server (2005) misinterpreting this ISO 8601 format date? (YYYY-MM-DD)
DECLARE #FromDate DATETIME
SET #FromDate = '2013-01-05'
PRINT #FromDate
-- Prints: May 1 2013 12:00AM
The date in text format, is clearly the 5th of January but for some reason SQL Server is interpreting as the 1st of may. There is no date format in the world which is YYYY-DD-MM so why is this happening? I've been using this format for years and never had a problem before so I'm not sure what's different in this instance.
Even if I force it into ISO8601 using CONVERT, it still gets it wrong:
DECLARE #FromDate DATETIME
SET #FromDate = CONVERT(VARCHAR, '2013-01-05', 126)
PRINT #FromDate
-- Still prints: May 1 2013 12:00AM
EDIT: Oops - I'm using 'CONVERT(VARCHAR above where I really mean CONVERT(DATETIME), so that's why that wasn't taking any effect. Thanks #RBarryYoung
However if I run either of the two examples above on a different server (SQL 2012) they both correctly print 'Jan 5 2013 12:00AM'
What's happening here? I thought one of the main reasons to use ISO format with SQL Server was that it made the month and day unambiguous?
It only makes it unambiguous for the newer datatypes (date/datetime2)
For backward compatibility this still is dateformat dependent for datetime.
On SQL Server 2012
SET DATEFORMAT DMY
SELECT CAST('2013-01-05' AS DATETIME), /*May*/
CAST('2013-01-05' AS DATETIME2), /*Jan*/
CAST('20130105' AS DATETIME), /*Jan*/
CAST('20130105' AS DATETIME2) /*Jan*/
You can use yyyymmdd as an unambiguous format when dealing with those datatypes.
See The ultimate guide to the datetime datatypes (this is referred to as the unseparated format in that article)

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'