SELECT CASE CAST Conversion Error

2019-06-05 16:03发布

问题:

I'm querying the back-end of an application. For what ever reason the developer decided to use NVARCHAR for all fields. I'm having a problem with one of the "date" fields--somehow it got populated with "97630886". There's a companion "time" field and for my query I'm trying to concatenate and CAST the results as a DATETIME. I'm trying to use a CASE statement but it's erroring: "The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.". Apparently all conditions are evaluated? Is there a way I can rewrite my SELECT statement to handle this?

SELECT CASE 
WHEN LOG_DATE IS NULL AND LOG_TIME IS NULL THEN NULL 
WHEN LOG_DATE IS NULL THEN LOG_TIME 
WHEN LOG_TIME IS NULL THEN LOG_DATE 
WHEN ISDATE(LOG_DATE) = 0 OR ISDATE(LOG_TIME) = 0 THEN LOG_DATE + ' ' + LOG_TIME 
ELSE CAST(LOG_DATE + ' ' + LOG_TIME AS DATETIME)
END AS [LogDateTime] 
FROM ...

回答1:

You can't mix datatypes in CASE expressions (or at least without taking care that they will implicitly cast OK)

when confronted with a stament like the following SQL Server will use datatype precedence to determine what the overall datatype of the expression should be

SELECT CASE WHEN 1=1 THEN 'not-a-date' ELSE getdate() END

For the above datetime has higher precedence than char so it implicitly casts the string to a date which fails.

The folowing succeeds however as sql_variant has a higher precedence

SELECT CASE WHEN 1=1 THEN cast('not-a-date' as sql_variant) ELSE getdate() END

So you can return multiple mixed datatypes that way (I'm not sure how easy sql_variant is to work with though)

Other than that you could return NULL for invalid datetimes instead of returning the nonsense data or cast everything to a string if you must return it.