Conversion failed for string ISO to datetime - sql

I am trying to convert a varchar(255) to datetime in SQL. I found this example:
DECLARE #IsoDate nvarchar(255)
SET #IsoDate = '2010-03-16T19:20:30.45123+01:00'
-- CONVERT TO DATETIME in SQL 2008
SELECT CAST(CONVERT(datetimeoffset, #IsoDate) AS datetime) as SQL2008
and it works perfectly. As I want to change the column format of a whole column, I tried
SELECT CAST(CONVERT(datetimeoffset, [col1]) AS datetime)
from [table]
but it gives me an error: Conversion failed when converting date and/or time from character string.
I don't get what the problem is, the only way it worked using the column is
SELECT CAST(Left([col1]),18) AS datetime)
from [table]
but I would prefer not to cut the string.

You can use
SELECT *
from [table]
WHERE TRY_CONVERT(datetimeoffset, [col1]) IS NULL
to see which values are causing issues.
If your version (since you have a comment with SQL Server 2008) is not supporting TRY_CONVERT and TRY_CAST you can select part of the records to find the issues using a loop/where clause.

but I would prefer not to cut the string.
Why? When converting DateTimeOffset to DateTime, the time zone information gets truncated anyway (see documentation), and since you've stated this solves your problem, it means that the only places where your string content is problematic is somewhere in that part of the string.
Also, since your string is ISO8601, you can safely use cast instead of convert (what's the point of using convert if you're not going to use the style parameter anyway?) - or better yet, use try_cast (unless you're working with a version lower than 2012, which in that case you should consider upgrading since it's the oldest version still supported) - so:
SELECT CAST(TRY_CAST([col1] AS datetimeoffset) AS datetime2(7))
FROM [table]
That being said, it would be better store time-zone aware datetime values in a DateTimeOffset data type - and other datetime values in DateTime2 data type (which is better than DateTime in every way).

Your code is failing because you have bad values. You can ignore them using try_convert():
SELECT CAST(TRY_CONVERT(datetimeoffset, [col1]) AS datetime)
FROM [table]
This is supported in all supported versions of SQL Server.
Because the timezone is ignored in this process, you might as well simply use:
select try_convert(datetime, left(col1, 23))

Related

String to datetime conversion in sql server

Is it possible to convert 'OCT-20' to '2020/10/01' in sql server. I tried the following cases without any luck.
select convert(date, 'OCT-20',103)
----Conversion failed when converting date and/or time from character string.
alter table MyTable alter column [period] date
----Conversion failed when converting date and/or time from character string.
I am using sql server 2016.
If we assume that the value is always in the format MMM-yy then you could do this:
SELECT CONVERT(date,'01-' + StringDate,106)
FROM dbo.YourTable;
Of course, this has 2 flaws.
The date uses a 2 digit year, so SQL Server could assume the wrong century
It'll only work if the LOGIN is using an English based language, otherwise it'll fail.
The real solution is to fix your design; never store date (and time) values in a varchar, and when ever you do use a varchar for a date (such as a literal in a WHERE) use an unambiguous format such as yyyyMMdd or yyyy-MM-ddThh:mm:ss.nnnnnnn.

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

Convert string YYYY-MM-DD to date datatype and handle conversion errors

I have 4 string-datatype columns in a SQL Server 2008 SP4 table that should be dates. I cant change that so I need a way to convert those strings to dates. The string is formatted as "YYYY-MM-DD".
For 2 of those columns, a CONVERT(datetime, [columname], 101) works but the other 2 have strings that go like this "1700-01-01" and when I try to convert them it shows a conversion out-of-range error.
I expect all strings values to be converted to a date, if the conversion fails I rather have it as a blank or any other way, I accept recommendations when handling date conversions errors. This table will be extensively used in applications made in C#/VBA and excel queries. Specifically for Excel, I need a friendly way to show this conversion errors in queries.
You can use TRY_CONVERT() which returns null if the conversion is not possible:
TRY_CONVERT(datetime, '1700-01-01', 101)
will return null instead of an error.
I think this works for SQL Server 2012+
If your version does not support it, you can check for the year part of the string and do something like this:
case
when left([columname], 4) < '1753' then null
else CONVERT(datetime, [columname], 101)
end
Depending on SQL Server version, you can try using:
TRY_CONVERT(DATETIME, [columnname], 101)
Instead of failing, this will produce a NULL value that you can then handle gracefully.
I didn't spot you're using SQL Server 2008. You could try using ISDATE() function.
SELECT CASE ISDATE('1700-01-01')
WHEN 1 THEN CONVERT(DATETIME, '1700-01-01', 101)
ELSE NULL
END AS Converted
This is probably best you can use. I'm not 100% sure if ISDATE() always behaves correctly, given that ISNUMERIC() has issues.

varchar vs datetime in sql

I was having problem in retrieving from SQL Server so I posted this [question][1]
I did not get any suitable answers. So I have changed the column datatype from datetime to varchar and now it works fine.
SELECT *
FROM test
WHERE (timeStamp BETWEEN '05-09-2013 18:23:57' AND '05-09-2013 18:23:59')
But my query if varchar datatype can play the role of datetime and in varchar we can also store the string then why sql provides datetime datatype? I know varchar occupies more space than datetime. I would like to know other reasons.
Change datatype of your column to datetime. You can do your query IF you'll use datetime instead of varchar in where clause:
select *
from test
where timeStamp between convert(datetime, '2013-09-05 18:23:57', 120) and convert(datetime, '2013-09-05 18:23:59', 120)
I'm pretty sure it would work even with implicit cast if you use ISO format of date:
select *
from test
where timeStamp between '2013-09-05 18:23:57' and '2013-09-05 18:23:59'
Here's more info about cast and convert.
Another reason apart from space is this:
Datetime has other functions like picking up the day, year, month,hours,minutes,seconds etc so that you don't have to write it for yourself. If you use varchar then it will be your responsibility to provide functions for future use. You should use split function to retrive the part of date you want.
Another is that a query on a varchar works slower when compared to Datetime when you use to conditions to compare month / day/ year
Always use proper DATETIME datatype to store date and time values. Refer this for more information
http://beyondrelational.com/modules/2/blogs/70/posts/10902/understanding-datetime-column-part-iv.aspx

Errors while trying to cast/convert VARCHAR to DATETIME in ANSI SQL

I have a column in a table where timestamps have been stored in VARCHAR format, but I need to compare these against a column of DATETIME values from another table to find time intervals, so I want to either cast or convert the VARCHAR timestamps to DATETIME. However, both casting and converting are giving me problems.
The format of the VARCHAR timestamp looks like this: "29/07/2012 01:53:36 +12".
Using the query:
SELECT CAST(event_timestamp AS datetime) FROM the_table
produces ERROR: date/time field value out of range: "29/07/2012 01:53:36 +12".
Using the query:
SELECT CONVERT(datetime, event_timestamp, 131) from the_table;
produces
ERROR: syntax error at or near ","
LINE 1: select CONVERT(datetime, event_timestamp, 131) from the_tab...
^ (note: this is pointing at the first comma).
The error with CONVERT actually happens even if you use a generic function such as getdate() for the data source. This db uses ANSI SQL-92 (or so I'm told). Could anyone please help me out with this?
This seems really painful, but the following should work:
select dateadd(hh, cast(right(tv, 3) as int),
CONVERT(datetime, left(tv, 10), 103)+CONVERT(datetime, substring(tv, 12, 8), 108)
)
from (select '29/07/2012 01:53:36 +12' as tv) t
I've never added datetime's before, but this just worked on SQL Server 2008.
Why can't SQL Server just support a flexible notation built around yyyy, mm, mmm, dd and so on?
The actual database is Aster Data, which is based on Postgres (as are most recent database engines). In this database, you would use to_timestamp(). See the documentation here http://www.postgresql.org/docs/8.2/static/functions-formatting.html. The call would be something like:
to_timestamp(val, 'MM/DD/YYYY HH:MI:SS tz') -- not sure if this gets the +12
There are no ANSI functions for date conversion, so each database does its own. Even string functions vary among databases (substr? substring? charindex? instr? location?), so there is no ANSI way to do this.
You are using the wrong syntax, try:
CONVERT(varchar(X), datetimeValue, 131)
Where X is the total number of characters desired.
You will then be able to search for a match with datetimeValue and event_timestamp, assuming each value share the same structure. This will allow you to match string against string.
If I'm not mistaken the standard (ANSI SQL) CAST operator always expect time/date/timstamp literals in ISO format ('YYYY-MM-DD')
But according to the manual for Teradata V12 (can't test it), the format of the CAST operator is
CAST(character_expression AS TIMESTAMP timestamp_data_attribute)
with date_data_attribute being a character value plus an optional FORMAT specifier.
So in your case this would probably be:
cast(event_timestamp AS TIMESTAMP FORMAT 'MM/DD/YYYY HH:MI:SS Z');
I'm not entirely sure about the format definition though. You'll probably need to adjust that
Btw: CONVERT isn't a standard SQL function. It's SQL Server specific.