Error handling function TRY_TO_TIMESTAMP not working as expected - snowflake-cloud-data-platform

I have a column (for ex Col1) which holds string value 'Jan 14 2019 5:30PM' and would like to convert it into timestamp_ntz(6) format in the target table in Snowflake.
Using Logic like this
INSERT INTO <target_table>
SELECT try_to_timestamp(<Col1>,'MON DD YYYY HH12:MI PM')
FROM <source_table>
This is throwing an error:
TRY_CAST cannot be used with arguments of type TIMESTAMP_NTZ(9) and TIMESTAMP_NTZ(9).

SELECT try_to_timestamp(column1,'MON DD YYYY HH12:MI PM')
FROM VALUES
('Jan 14 2019 5:30PM');
works:
TRY_TO_TIMESTAMP(COLUMN1,'MON DD YYYY HH12:MI PM')
2019-01-14 17:30:00.000
BUT pre-parsing the string to an actually timestamp, and then trying to parse that fails
SELECT try_to_timestamp(column1,'MON DD YYYY HH12:MI PM')
FROM VALUES
(to_timestamp('Jan 14 2019 5:30PM','MON DD YYYY HH12:MI PM'));
gives the error:
Function TRY_CAST cannot be used with arguments of types TIMESTAMP_NTZ(9) and TIMESTAMP_NTZ(9)
original this type of problem would also happen if you passed a BOOLEAN to TRY_TO_BOOLEAN.
If you do not know if "all you input is timestamps or text (like if it's coming from a VARIANT data where auto magic conversion could be happening.
I would say
You can cast to ::TEXT and then parse again.
but that also errors.
is_timestamp_ntz(b)
Fails if passed non-variant data. So that's not helpful.
A really yucky work around:
setup:
create temp table data(json variant);
insert into data select parse_json(column1) as json
FROM VALUES
('{"date":"Jan 14 2019 5:30PM"}'),
('{"date":"2021-01-24 12:34:56"}');
sql:
SELECT
is_timestamp_ntz(json:date) as a
,try_to_timestamp_ntz(json:date::text,'MON DD YYYY HH12:MI PM') as b
,try_to_timestamp_ntz(json:date::text) as c
,try_to_timestamp_ntz(nvl(b,c)::text) as d
,nvl(try_to_timestamp_ntz(json:date::text,'MON DD YYYY HH12:MI PM'),try_to_timestamp_ntz(json:date::text)) as sigh
FROM data;
thus I suggest opening a support ticket, as it's gross the auto classification of JSON data, then exploding the parsing code, and in the mean time here is the work around, cast it to text, and parse if your expected format, and let the system default catch the things there where timestamp, that are turned to text, and then back again.
nvl(try_to_timestamp_ntz(json:date::text,'MON DD YYYY HH12:MI PM'),try_to_timestamp_ntz(json:date::text)) as sigh

try this:
select try_cast(to_varchar(column1) as timestamp) from table;

Related

Keep null as empty and convert nvarchar to date

expiredDate nvarchar() column contains data like 22-12-2022 00:00:00 and null.
SELECT ISNULL(CONVERT(Date, expiredDate), '')
FROM tablename
Result for null is default date 1900-01-01 - I want it to be blank or empty.
As the column is getting converted to datetime null is converted to the default date.
Required date should be in yyyy-MM-dd format and null as empty
You may use CONVERT here on the raw date to generate a string, and then COALESCE missing null values into empty string:
SELECT expiredDate,
COALESCE(CONVERT(varchar(10), expiredDate, 120), '') AS expiredDateText
FROM yourTable;
You can try below query.
select case when ISDATE(expiredDate) = 0 then '' else convert(varchar,convert(date,expiredDate)) end as YourColumnName
The ISDATE() function checks whether the input data is a valid date or not. This includes NULL too. It will return Zero (0) if the data is not a date.
If you culture is en-us then by default you will get the date in YYYY-MM-DD format.
You can also use Format function in SQL Server to get the date in your expected format.
More information about format function can be found at below link.
https://learn.microsoft.com/en-us/sql/t-sql/functions/format-transact-sql?view=sql-server-ver15
You've have stumbled upon one of the odd(annoying) quirks in SQL Server where blank string becomes 1900-01-01 when cast to DATE. Your CONVERT() sets the column type to DATE, and then when you do ISNULL, it implicitly casts empty string to DATE. Why it returns 1900-01-01 instead of an error, I have no idea
Example of Empty String to Date Odd Behavior
SELECT CAST('' AS DATE)
--Returns 1900-01-01
Parse Date to Correct DATE data type and Then Format
How I'd recommend this is first converting your NVARCHAR column to the correct DATE data type. Using TRY_CAST allows any invalid dates to not cause the whole query to fail, instead will return NULL. FORMAT() then allows you to format the DATE anyway you like, and ISNULL will change NULL to empty string
DECLARE #YourTable TABLE (ID INT IDENTITY(1,1),expiredDate nvarchar(20))
INSERT INTO #YourTable
VALUES ('22-12-2022 00:00:00'),('31-12-2022 00:00:00'),('02-02-2022 00:00:00'),(NULL)
,('40-02-2022 00:00:00') /*Bad date for testing purposes*/
SELECT *,FormattedExpiredDate = ISNULL(FORMAT(B.ExpiredDateWithCorrectDateType,'yyyy-MM-dd'),'')
FROM #YourTable AS A
/*Format to YYYY-MM-DD (culture agnostic date format) and then use TRY_CAST(). If date is invalid, will return NULL*/
CROSS APPLY (SELECT ExpiredDateWithCorrectDateType = TRY_CAST(SUBSTRING(expiredDate,7,4) + SUBSTRING(expiredDate,4,2) + SUBSTRING(expiredDate,1,2) AS DATE)) AS B
Results:
ID
expiredDate
ExpiredDateWithCorrectDateType
FormattedExpiredDate
1
22-12-2022 00:00:00
2022-12-22
2022-12-22
2
31-12-2022 00:00:00
2022-12-31
2022-12-31
3
02-02-2022 00:00:00
2022-02-02
2022-02-02
4
NULL
NULL
5
40-02-2022 00:00:00
NULL

Cast or convert varchar 'd/mm/yyyy' to dd/mm/yyyy (date or timestamp)?

An import has rendered a date [YEAR] as varchar and I need to convert it to a proper date.
The conversion fails I believe, because SQL cannot recognise d/mm/yyyy equal to dd/mm/yyyy.
How do I get SQL to convert / cast this into a date or timestamp?
SELECT [YEAR], LEN([YEAR]) AS ColumnLength
FROM [IDW_Dev]
YEAR ColumnLength
10/07/2020 10
8/07/2020 9
14/08/2020 10
I tried this, and this should normally work:
, CAST([YEAR] AS DATE) AS AUDIT_DATE
Conversion failed when converting date and/or time from character string.
Here's a demo using the convert function, just because I felt like testing if it worked with all variations of DD and MM in the string.
Convert has most layouts built in, 103 is for British/French format with slashes.
SELECT SampleDate
, CONVERT(Datetime2, SampleDate, 103) AS ConvertedDate
FROM (
VALUES ('1/2/2020')
, ('1/02/2020')
, ('01/2/2020')
, ('01/02/2020')
)Samples(SampleDate)

SQL Date-Time Conversion with nested converts experiences random conversion errors

Looking for assistance with a strange issue if anyone has ideas:
I have a SQL that statement works most of the time in a T-SQL script but crashes occasionally. I have identified the data that a crash occurs on and cannot identify any difference between data rows that work.
The goal of this code is to add the time to an already existing datetime value that has 00:00:00 as the time from the second time column (as outlined below). My goal is to combine both columns into YYYY-MM-DD HH:MM:SS format, but I had to convert them to char first to trim off the orignal 00:00:00.
Columns
LogDate - contains date only in DateTime format (YYYY-MM-DD HH:MM:SS)
LogTime - contains the time of the action and is in varchar format (HH:MM)
SQL Conversion
SELECT CONVERT(DATETIME, CONVERT(CHAR(8), LogDate, 112) + ' ' + CONVERT(CHAR(8), LogTime, 108))
FROM TestTable
WHERE EventSerial = '100001'
However, if I change the EventSerial in the above statement to a different row, such as '100002', the statement works.
The data for each row is below:
EventSerial 100001's values:
LogDate: 2015-04-02 00:00:00.000
LogTime: 10:04
EventSerial 100002's values:
LogDate: 2015-04-02 00:00:00.000
LogTime: 10:48
Running with data set 1 fails, running with data set 2 produces output. Also, running the code without the final datetime conversion works, or if I run the code with the string manually it works (as outlined below:)
SELECT CONVERT(CHAR(8), LogDate, 112) + ' ' + CONVERT(CHAR(8), LogTime, 108)
FROM TestTable
WHERE EventSerial = '100001'
SELECT CONVERT(DATETIME, '20150402 10:48')
SELECT CONVERT(DATETIME, '20150402 10:04')
Any suggestions, I'm sure its something silly that I'm missing (and I probably took the long way around the issue anyway. The desired output would be 2015-04-02 10:04:00
First, datetime has no format. (why?)
Second, you don't need to convert the datetime value to char to add hours and minutes, just use DateAdd:
SELECT DATEADD(Minute,
CAST(RIGHT(LogTime, 2) as int),
DATEADD(Hour,
CAST(LEFT(LogTime, 2) as int),
LogDate
)
)
FROM TestTable
WHERE EventSerial = '100001'
Also, note that convert does not hold a style for yyyymmdd hh:mm
Note: code was written directly here, there might be some mistakes.
I'm not sure why you're getting the error... possibly there are some unseen characters in your varchar time field... like a tab or something maybe? Try this query:
SELECT ascii(substring(LogTime,1,1)) Char1,
ascii(substring(LogTime,2,1)) Char2,
ascii(substring(LogTime,3,1)) Char3,
ascii(substring(LogTime,4,1)) Char4,
ascii(substring(LogTime,5,1)) Char5
FROM TestTable
WHERE EventSerial = '100001'
It should show these results:
Char1 Char2 Char3 Char4 Char5
----------- ----------- ----------- ----------- -----------
49 48 58 48 52
(1 row(s) affected)
This would be a bit more efficient:
select dateadd(minute, datediff(minute,0, LogTime), LogDate)
FROM TestTable
But this assumes that your date field always has 00:00:00 time information. If you want to be sure that is stripped out as well you could use:
select dateadd(minute, datediff(minute,0, LogTime), dateadd(day, datediff(day, 0, Logdate),0))
FROM TestTable

How to get the date from a varchar

I have an issue retrieving the data that I would like. I have a Varchar column that consist of various information. I would like to extract the date from that column only. However, I have been unsuccessful. I used the following SQL(2008) to get the data below, But I can't seem to just get the date only without the time. Obviously, the date and time are in different position. Hope you can help.
SELECT substring(Data, 8, 17)
from mastInfo
9/25/2013 12:36:5
Jul 8 2013 11:40
9/25/2013 12:43:5
SELECT convert(date, Case When IsDate(substring(Data, 8, 17)) = 1
Then substring(Data, 8, 17)
Else NULL END)
from mastInfo
Since you are starting off with a string, it is possible that it does not represent a valid date. Using the IsDate function will return 1 when the string can be converted to a date. Basically, this code will convert to date those values that can be converted, and will return NULL for those values that cannot be converted to a valid date.
If you are using SQL Server 2012 or newer, then you can use Try_Convert().
Here's the SQL Fiddle.
Here's an example (from the above SQLFiddle):
Select Try_Convert(datetime, DateAsString) As DateAsDateTime
,DateAsString
From SomeTable
Here's the result:
DATEASDATETIME DATEASSTRING
September, 25 2013 12:36:05+0000 9/25/2013 12:36:5
September, 25 2013 12:43:05+0000 9/25/2013 12:43:5
July, 08 2013 11:40:00+0000 Jul 8 2013 11:40
if you want convert it to date time use :
SELECT CONVERT(Datetime, '2011-09-28 18:01:00', 120) -- to convert it to Datetime
if you want get time :
SELECT LTRIM(RIGHT(CONVERT(VARCHAR(20), '2011-09-28 18:01:00', 100), 7))
if you want date part :
SELECT CONVERT (DATE, GETDATE())
what version of sql server?
can you try this:
SELECT convert(date, substring(Data, 8, 17))
from mastInfo
First convert Varchar into DateTime and after that again convert it in varchar in desired date format like 101,102,103
Try this:
select convert(varchar(50),convert(datetime,'9/25/2013 12:43:5'),101)

Format a string type into a datetime format

i have a column (nvarchar),there are datetimes in there but as a string.I want to change that column's type into smalldatetime but before i want to format all string dates into a same datetime format.But i cant succeed it.Some of them are like this "2007-07-10",some of them are reverse of this "02.07.2008". How can i change them into one format for example dd.mm.yyyy.
(ms sql server 2008)
If you only have those 2 formats, this is how you can do it.
I am assuming
'02.07.2008' has format 'dd.mm.yyyy'
'2007-07-10' has format 'yyyy-mm-dd'
If you have more formats than that, you have to alter the 'case' in the 'select' clause accordingly
declare #t table (a varchar(12))
insert #t values ('02.07.2008')
insert #t values ('2007-07-10')
select convert(date, a, case when charindex('-',a) = 5 then 21 else 103 end)
from #t
Output
2008-07-02
2007-07-10
The format is standard for a date field, but if you want to store it as a varchar, you can format it as dd.mm.yyyy like this instead.
select replace(convert(varchar, convert(date, a, case when charindex('-',a) = 5
then 21 else 103 end), 103), '/', '.')
from #t
Output
02.07.2008
10.07.2007
I have to point out that you should always store a date as a date and not a varchar in the database when possible.
You can't do it unless you know the exact format.
Think about the different formats - in some countries the month comes first, while in the other it's the day. So if you don't know whether 02.07.2008 means July 2th, or it means Feb 7th, then you can't possibly accomplish your task.

Resources