The postings on this site are my own and do not represent my Employer's positions, advice or strategies.

LifeAsBob - Blog

 

Home

No Ads ever, except search!
Thursday, April 25, 2024 Login
Public

isdate(), derived tables and CTE 1/6/2009 3:24:16 PM


UPDATE - 01/29/2009 - I just received a solution to this issue, that does not require a temp table, which was my wimpy solution, thanks to Shawn who left this great solution in the comments:

Select * 
    From #checkDates
    where convert(datetime,case isdate(rptDate) when 1 then rptDate else null end)
Between
        '02/27/2009' and '02/28/2009'


The isdate() function does not work properly (or at least as I expect it would) when it is used inside a derived table or a Common Table Expression.  This is really frustruating as it changes the way I think of derived tables and CTE's.  I always assumed that the inner query or CTE was resolved first, but if you follow the TSQL below, you can see that is not the case.

This may affect other functions, isnumeric() or even custom functions, so test them carefully.

I was working on a report issue that was generating an invalid derived date from a varchar, 02/29/2009.  Very simple to filter out, but due to the way the where clause is resolved / short circuited in tsql, it was going to be necessary to use a derived table or a CTE, but neither would work.  I ended up resorting to using an additional temporary table (wimpy, wimpy), I don't like this solution and would like to find one that does not require the temporary table.

Here is the problem:


create table #checkDates
    (chkDtId int identity(1,1) primary key,
        rptDate varchar(10))

Insert into #checkDates (rptDate) values ('02/26/2009')
Insert into #checkDates (rptDate) values ('02/27/2009')
Insert into #checkDates (rptDate) values ('02/28/2009')
Insert into #checkDates (rptDate) values ('02/29/2009')

-- This fails below with invalid date
Select * 
    From #checkDates
    where convert(datetime,rptDate) Between
        '02/27/2009' and '02/28/2009'

-- put the isdate function as part of where clause
-- select statement still fails
Select * 
    From #checkDates
    where isdate(rptDate) = 1 and
        convert(datetime,rptDate) Between
        '02/27/2009' and '02/28/2009'

-- switch to a derived table, the thought being to
-- remove the invalid dates from the inner select 
-- somehow in my mind i think the inner query should be resolved first,
-- but this is not the case !
Select * from 
    ( Select * 
    From #checkDates
    where isdate(rptDate) = 1 ) x
    where convert(datetime,rptDate) Between
        '02/27/2009' and '02/28/2009'

-- wimpy solution is to select the "good" records into 
-- a temp table and then perform the next select, yuck
-- BUT IT WORKS
Select * into #InterimResults 
    From #checkDates
    where isdate(rptDate) = 1 

Select * from #InterimResults
    where convert(datetime,rptDate) Between
        '02/27/2009' and '02/28/2009'
--
-- CTE SOLUTION, DOES NOT WORK EITHER 
--
WITH goodDate_CTE AS (
    Select * 
    From #checkDates
    where isdate(rptDate) = 1 
)
SELECT *
FROM goodDate_CTE
where convert(datetime,rptDate) Between
        '02/27/2009' and '02/28/2009'

Blog Home