0

I'm having trouble wrapping my head around using a variable to store a function. I want to store the following function in a variable:

declare @agegroup int
set @agegroup = datediff(year, convert(date, p.date_of_birth), getdate())

Doing this produces an error:

Msg 241, Level 16, State 1, Line 3
Conversion failed when converting date and/or time from character string.

I believe that this is happening because SQL doesn't know what p.date_of_birth is yet. It's a column from a table in a query.

select p.date_of_birth from person p

I will need to reference the function in the variable numerous times in the query (once it's complete), so I want to neaten up my query by using a variable. It this possible?

Edit: I was asked to include some data for the field in my sample code. The DOB is stored as a string: yyyymmdd

19350919
19370607
19370607
19400814
19410128
19410128
12
  • 2
    No, this is happening because you are storing a date as a string -- a no-no -- and then trying to convert it to a date. The format is invalid. Commented Feb 13, 2018 at 16:02
  • 2
    Why isn't date_of_birth already a date? Commented Feb 13, 2018 at 16:03
  • set @agegroup = datediff(year, convert(date, p.date_of_birth), getdate()) doing this will NEVER produce this error Conversion failed when converting date and/or time from character string. Commented Feb 13, 2018 at 16:03
  • @Pரதீப் Really? What if date_of_birth is '20180231'? Commented Feb 13, 2018 at 16:04
  • 1
    There's nothing wrong with SELECT CONVERT(date,'18840218');. I'm still very much of mind that you have a fictitious date in your data. Commented Feb 13, 2018 at 16:55

1 Answer 1

3

First, I assume your code is taken out of context, because p is not defined. That's okay.

Your problem is that date_of_birth is stored as a string. Fix that problem, by storing it as a date. SQL databases have date/time types for a reason. Use them.

You can eliminate the error in your code by using try_convert():

set @agegroup = datediff(year, try_convert(date, p.date_of_birth), getdate())

In SQL Server 2008, a reasonable approximation is:

set @agegroup = datediff(year, (case when isdate(p.date_of_birth) = 1 then p.date_of_birth end), getdate())

You can identify the offending values by doing:

select date_of_birth
from p
where try_convert(date, date_of_birth) is null and date_of_birth is not null;
Sign up to request clarification or add additional context in comments.

5 Comments

Hi Gordon, Is there any way to get around this problem? I can't edit the structure of this table (it's proprietary). Can't I try converting the column to date in a var first?
@theeviininja He already showed you a way to get around the problem - add try_convert() to your query. Of course you could fix the data in the table, even if you can't fix the data types, but you'll have to do this over and over again unless you also put something in place to prevent more bad data from getting in there in the first place.
@GordonLinoff I forgot to mention that this is SQL Server 2008, not 2012, so Try_Convert isn't an option, unfortunately. I updated the title of my post.
@theeviininja . . . You should include sample data in the question so we know what the dates are supposed to look like.
@theeviininja On ancient versions like that you can use CONVERT(date, CASE WHEN ISDATE(p.date_of_birth) = 1 THEN p.date_of_birth END) which is essentially what TRY_CONVERT() is doing. But you need to (a) clean up the data (identify it with WHERE ISDATE(date_of_birth) = 0) and (b) go back to the vendor and tell them their design is moronic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.