Cast to datetime only if its a date value - sql

I have a table with DateFrom column
it's an nvarchar col in the col I have data like that
01
02
10/10/2020
04
some strings and some DateTime values
I need to cast it to DateTime but only if it's a date if not then pull out the value like it is can is this possible?
thanks ...

a Simple Try cast should do the job here
DECLARE #Table TABLE (Val NVARCHAR(20))
INSERT INTO #Table
VALUES('1'),('2'),('10/10/2020'),('04')
SELECT
*,
TRY_CAST(Val AS DATE)
FROM #Table
Results

Something like this should work. It uses a CASE statement to check whether or not the value is a valid date and if so casts it to DATETIME, then converts it to VARCHAR (so dates and other values can be returned as the same column).
You can find other datetime to string styles here if you need them formatted differently:
https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver15
DECLARE #TempTable TABLE (Dt NVARCHAR(30))
INSERT INTO #TempTable
VALUES('1'),('2'),('10/10/2020'),('04'),('Jun 27 2021 12:22AM'),('Oct 12 2021 8:31PM')
SELECT
*,
CASE WHEN ISDATE(Dt) = 1 THEN Convert(VARCHAR, CAST(Dt AS DATETIME), 120) ELSE Dt END
FROM #TempTable

You can easily check this with the case statement.
Postgres example
select case when '12/12/2021' ~ '\d{2}\/\d{2}\/\d{4}' then 'this is the date' ELSE 'this is a string' end;
->this is the date
select case when 'some text' ~ '\d{2}\/\d{2}\/\d{4}' then 'this is the date' ELSE 'this is a string' end;
->this is a string
so you can use it like this
select case when fild_01 ~ '\d{2}\/\d{2}\/\d{4}' then TO_DATE(fild_01,'DD/MM/YYYY')::text ELSE fild_01 end from test_table;
as you can see, case construction can't generalize two different types of data, so I had to convert them to the same type of text

Use the TRY_CONVERT function, with style 107
SELECT TRY_CONVERT(datetime, 'Jun 27 2021 12:22AM', 107)
Result
2021-06-27 00:22:00.000
This returns a null if the value is not a date

You can choose according to your needs.
When you want to set default value:
SELECT IIF(ISDATE(Val) = 1 , Val,'YOUR_DEFAULT_VALUE')
Whent default value not matter (It will be NULL):
SELECT TRY_CAST(NULL AS DATE)

Related

Issue in using TRY_PARSE in CASE WHEN Statement

I need to validate the dates with different formats like
Thursday March 15, 2018, 05-21-1995, 04.03.1934 and I may get Invalid Dates like N/A, #### etc.,. I am using the Following Query to validate the date in Stored procedure, here I insert the date into the date column and set Error Flag If there is an Invalid date.
INSERT INTO table_name(date_column,date_error)
SELECT
CASE WHEN TRY_PARSE(date_column AS datetime USING 'en-US') is NULL THEN date_column
ELSE TRY_PARSE(date_column AS datetime USING 'en-US')
END as date_column,
CASE WHEN TRY_PARSE(date_column AS datetime USING 'en-US') is NULL THEN 1
ELSE 0
END as date_error
FROM #temp_table;
I'm getting the Error as Conversion failed when converting date and/or time from character string for date value ####.
You cannot put two different types in one column
This may work for you
declare #T table (pk int identity primary key, varDt varchar(100));
insert into #T (varDt) values ('Thursday March 15, 2018'), ('05-21-1995'), ('N/A'), ('####'), ('easter'), ('');
declare #Tf table (pk int primary key, varDt varchar(100), needFix bit, dt datetime);
insert into #Tf
select t.pk, t.varDt
, case when TRY_PARSE(t.varDt AS datetime USING 'en-US') is null then 1 else 0 end as needFix
, TRY_PARSE(t.varDt AS datetime USING 'en-US') as dt
from #T t;
select *
from #Tf tf
order by needFix desc, pk;
Thanks for all your comments. As #gordon-linoff said we can't have two different datatypes in CASE WHEN Statement. So, I CAST the else statement to varchar.
INSERT INTO table_name(date_column,date_error)
SELECT
CASE WHEN TRY_PARSE(date_column AS datetime USING 'en-US') is NULL THEN date_column
ELSE CAST(TRY_PARSE(date_column AS datetime USING 'en-US') AS varchar(max))
END as date_column,
CASE WHEN TRY_PARSE(date_column AS datetime USING 'en-US') is NULL THEN 1
ELSE 0
END as date_error
FROM #temp_table;

Need Help In SQL For Date

01/12/2016, 02/12/2016, 03/12/2016
In SQL I had a these three dates in single record or single cell, but I want to take first date as from date and last date as end date.
I need any syntax for that. Can some one help me?
If the data structure is same for all values, then you can try as below
DECLARE #val AS TABLE (val NVARCHAR(max))
INSERT INTO #val
SELECT'01/12/2016, 02/12/2016, 03/12/2016'
SELECT *FROM #val
SELECT CAST (LEFT(val,10) AS DATE) AS startdate , CAST (RIGHT(val,10) AS DATE) AS enddate FROM #val

Converting YYYYMM format to YYYY-MM-DD in SQL Server

I need to perform a query on a large table that has a datetime column that is indexed.
We need to query the data for a range from a month (at a minimum) to multiple months.
This query would be executed from Cognos TM1 and the input would be a period like YYYYMM. My question is - how to convert the YYYYMM input to a format that can be used to query that table (with the index being used).
Let's say if the input is
From Date: '201312'
To Date: '201312'
then, we need convert the same to 'between 01-12-2013 and 31-12-2013' in the query
Since we need this to be hooked up in Cognos TM1, so would not be able to write a procedure or declare variables (TM1 somehow does not like it).
Thanks in advance for your reply.
I would do something like this:
create procedure dbo.getDataForMonth
#yyyymm char(6) = null
as
--
-- use the current year/month if the year or month is invalid was omitted
--
set #yyyymm = case coalesce(#yyyymm,'')
when '' then convert(char(6),current_timestamp,112)
else #yyyymm
end
--
-- this should throw an exception if the date is invalid
--
declare #dtFrom date = convert(date,#yyyymm+'01') -- 1st of specified month
declare #dtThru date = dateadd(month,1,#dtFrom) -- 1st of next month
--
-- your Big Ugly Query Here
--
select *
from dbo.some_table t
where t.date_of_record >= #dtFrom
and t.date_of_record < #dtThru
--
-- That's about all there is to it.
--
return 0
go
Suppose you are getting this value of YYYYMM in a varchar variable #datefrom .
You can do something like
DECLARE #DateFrom VARCHAR(6) = '201201';
-- Append '01' to any passed string and it will get all
-- records starting from that month in that year
DECLARE #Date VARCHAR(8) = #DateFrom + '01'
-- in your query do something like
SELECT * FROM TableName WHERE DateTimeColumn >= #Date
Passing Datetime in a ansi-standard format i.e YYYYMMDD is a sargable expression and allows sql server to take advantage of indexes defined on that datetime column.
here is an article written by Rob Farley about SARGable functions in SQL Server.
Try this...
declare #startdate date,#endate date
select #startdate =convert(date,left('201312',4)+'-'+right('201312',2)+'-01')
select #endate= DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, #startdate) + 1, 0))
select convert(date,#startdate,102) startdate,convert(date,#endate,102) endate
In the datasource of your TM1 Turbo Integrator process, you can use parameters in the SQL query. E.g. you could take this SQL query:
SELECT Col1, Col2
FROM Table
WHERE Col1 = 'Green'
AND Col2 < 30
In TM1, to parameterise this, you would create two parameters e.g. P1 and P2 and put them in the query:
SELECT Col1, Col2
FROM Table
WHERE Col1 = '?P1?'
AND Col2 < ?P2?

SQL Server - Converting date in "20140410" format to 04/10/2014 format

I have a table in a server that outputs the date in the following format YEARMONTHDAY
Example 20140410.
Question is how to I convert it to be as MONTH/DAY/YEAR, example 04/10/2014
Thanks!
David
Try this:
declare #theDate varchar(8)
set #theDate = '20140410'
select convert(varchar(10),cast(#theDate as date),101)
I think you can use:
SELECT convert(varchar, getdate(), 101);
Here is one way to do it:
declare #dt CHAR(8) = '20140131'
select #dt, CONVERT(DATE,#dt) as newDt
Here is a link on the CONVERT function http://msdn.microsoft.com/en-us/library/ms187928.aspx and one on date types http://msdn.microsoft.com/en-us/library/bb630352.aspx
Here are 2 different versions, one version for if all values are valid YYYYMMDD format, and one that will still work with invalid dates (but will return null for invalids).
DECLARE #tblTest TABLE (id int not null identity, myDate int not null)
INSERT INTO #tblTest(myDate)
VALUES(20140308),(20140410)
;
--QUERY 1: if all values in your table are valid dates, then you can use this
SELECT t.id, t.myDate
, myDateFormatted = CONVERT(varchar(10),CONVERT(DATE, CONVERT(VARCHAR(10),t.myDate)),101)
FROM #tblTest t
--NOW INSERT SOME INVALID DATES AS WELL
INSERT INTO #tblTest(myDate)
VALUES(20140132),(48)
;
--NOW IF THERE ARE INVALID DATE, THEN USING QUERY 1 WOULD CAUSE AN ERROR: Conversion failed when converting date and/or time from character string
--QUERY 2: if there are ANY invalid values in your table, then you can use this
SELECT t.id, t.myDate
, myDateFormatted =
CASE
WHEN ISDATE(t.mydate) = 1 and len(t.myDate) = 8
THEN CONVERT(varchar(10),CONVERT(DATE, CONVERT(VARCHAR(10),t.myDate)),101)
ELSE NULL --THIS IS AN INVALID DATE
END
FROM #tblTest t
;

Is there a safe way to cast SQL datetimes?

Pretty simple question that I can't quite find the answer for:
Is there a simple and safe† way to cast a varchar to datetime in SQL Server?
† i.e. gracefully handle non-datetime strings with a default datetime value
You can filter your rows using the isdate function. This query returns three rows without any conversion errors:
with v as (
select '20110714' value union all
select '2011-07-15' union all
select '3/22/2011' union all
select 'foo'
)
select cast(value as datetime)
from v
where isdate(value) = 1
Edit
When you want a default vaue (like the current date/time), you could do something like this:
select case when isdate(value) = 1 then cast(value as datetime) else getdate() end
From SQL Server Denali you can use TRY_CONVERT. A case expression is the only safe way in previous versions.
You could try
select cast ('28/08/2006 11:23:25' as datetime)
SELECT * FROM tab_val WHERE (CASE ISDATE(val) WHEN 1 THEN CAST(val As DateTime) ELSE NULL END)
More details in the manual
we can place a check that column have the valid datetime and if not then return nulls not genrating any error.
SELECT CASE ISDATE([YourDate]) WHEN 0
THEN CAST([YourDate] AS DATETIME)
ELSE CAST(NULL AS DATETIME) END AS [Your Date]
FROM [dbo].[yourtable]