Reputation: 183
I suspect that I am not understanding how the CASE expression evaluates.
When I run this statement, I'm getting:
Msg 242, Level 16, State 3, Line 7
The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value.
which, I understand; however, I'm not sure why. In the CASE
expression, WHEN 1
should be evaluated and no CAST
should take place.
Am I misunderstanding how CASE
works?
DECLARE @parameterID int = 42;
DECLARE @userID int = 3;
DECLARE @administratorID int = 2;
--parameterid of 42 has a parametertype of 1
With Param AS
(
SELECT
ParameterValue, USER_ID, P.PARAMETERTYPE_ID AS ParameterType
FROM
dbo.ParameterValues PV
INNER JOIN
Parameters P on P.ID = PV.PARAMETER_ID
WHERE
PARAMETER_ID = @parameterID AND USER_ID = @userID
UNION ALL
SELECT
ParameterValue, USER_ID, P.PARAMETERTYPE_ID AS ParameterType
FROM
dbo.ParameterValues PV
INNER JOIN
Parameters P on P.ID = PV.PARAMETER_ID
WHERE
PARAMETER_ID = @parameterID AND USER_ID = @administratorID
)
SELECT TOP 1
TypedParmValue =
CASE P1.ParameterType
WHEN 1 THEN P1.ParameterValue
WHEN 2 THEN CAST(P1.ParameterValue AS datetime)
WHEN 3 THEN CAST(P1.ParameterValue AS DECIMAL(20,6))
WHEN 4 THEN CAST(P1.ParameterValue as bit)
ELSE P1.ParameterValue
END,
P1.ParameterType,
P1.ParameterValue,
PT.ParameterTypeName
FROM
Param P1
INNER JOIN
ParameterTypes PT on P1.ParameterType = PT.ID
ORDER BY
USER_ID DESC
Functionally, what I'm trying to do is look up a parameter (value is stored 'generically' as nvarchar) and then convert it to the proper datatype based on the type (as stored in parametertype). The CTE is used to look for a user-specific parameter value or fallback to the default value. I know that there are different/better ways of dealing with default parameters.
Upvotes: 1
Views: 45
Reputation: 754438
Yes, you've misunderstood how CASE
works.
First of all, it's an expression (like a+b
) - not a statement.
Therefore, CASE
has to return one atomic value (from several possibilities) - and all those return values have to be of the same datatype.
In your case - this is totally not the case; in such a situation, SQL Server will pick the datatype that's highest on the data type precedence list - which here is DATETIME
.
So all values being returned will be attempted to be converted to DATETIME
- and if P1.ParameterValue
for WHEN 1
isn't a valid DATETIME
, this error occurs.
Upvotes: 1