Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
356 views
in Technique[技术] by (71.8m points)

sql server - Conversion failed when converting the varchar value in case statement

I cant not get my head around it. We have following simple query.

DECLARE @bFlag bit
SET @bFlag = 0
SELECT  something = CASE
                WHEN @bFlag = 1 THEN
                    CASE
                        WHEN RS.intInterval = 1 THEN '"Days"'
                        WHEN RS.intInterval = 2 THEN '"Weeks"'
                        WHEN RS.intInterval = 3 THEN '"Months"'
                        WHEN RS.intInterval = 4 THEN '"Years"'
                    END
                Else 
                    RS.intInterval
                End
from    MyTable  AS RS WITH (NOLOCK)

So I want to get intInterval(which is int) if flag is not set to true. Otherwise if flag is set to true, I want to get Days, Weeks, etc depending upon value of intInterval. If I run this with @bFalg = 1, I get this error:

Conversion failed when converting the varchar value '"Weeks"' to data type int

which does not make any sense as I am not converting anything.

I know I can fix it by putting cast (intInterval as varchar) in else part. However I want to know the reason why I am getting this error, why case is trying to convert 'Weeks' to int?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When using CASE statement, all result expressions must have the same data type. If not, the result will be converted to the data type with a higher precedence. According to BOL:

Returns the highest precedence type from the set of types in result_expressions and the optional else_result_expression.

Since INT has a higher data type precedence than VARCHAR, "Weeks" get converted to INT and that produces the error:

Conversion failed when converting the varchar value '"Weeks"' to data type int

Another example that will produce the same error:

SELECT CASE WHEN 1 = 1 THEN 'True' ELSE 0 END

The solution is to convert RS.intInterval to VARCHAR:

CONVERT(VARCHAR(10), RS.intInterval)

Your final query should be:

DECLARE @bFlag bit
SET @bFlag = 0
SELECT  something = CASE
                WHEN @bFlag = 1 THEN
                    CASE
                        WHEN RS.intInterval = 1 THEN '"Days"'
                        WHEN RS.intInterval = 2 THEN '"Weeks"'
                        WHEN RS.intInterval = 3 THEN '"Months"'
                        WHEN RS.intInterval = 4 THEN '"Years"'
                    END
                Else 
                    CONVERT(VARCHAR(10), RS.intInterval)
                End
from    MyTable  AS RS WITH (NOLOCK)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...