存储过程尝试将varchar转换为int,原因不明

时间:2015-08-17 14:38:42

标签: sql sql-server asp.net-mvc sql-server-2008 stored-procedures

我正在使用SQL参数来允许用户使用视图中的下拉菜单创建自己的SELECT查询。参数值使用MVC控制器中的实体框架从视图传递给存储过程。

我正在尝试避免动态SQL,所以我有几个选项可以做到这一点。

这是我最终选择的方法:

    @topLeftInput varchar(100),
    @topRightInput varchar(100)
AS
BEGIN
        Select  * from test
            where 
                CASE @topLeftInput 
                    WHEN 'BasicReturnReasonId' THEN BasicReturnReasonId
                    WHEN 'ClientName' THEN ClientName
                    WHEN 'CreditDeniedReasonId' THEN CreditDeniedReasonId
                    WHEN 'ItemsnotReturnedReasonId' THEN ItemsnotReturnedReasonId
                    WHEN 'ManufacturerId' THEN ManufacturerId
                    WHEN 'ManufacturerOrderNumber' THEN ManufacturerOrderNumber
                    WHEN 'ProductConditionId' THEN ProductConditionId
                                ELSE NULL
                    END
                = @topRightInput;
END

@topLeftInputClientNameManufacturerOrderNumber时发生异常。当@topLeftInput等于其中任何一个时,用户可以在文本框中输入@topRightInput的值,而不是使用下拉列表。

enter image description here

我收到一个异常,说明将varchar值转换为int时出错。不确定为什么要这样做。

在我之前使用的技术中,这个例外并没有发生,并且它工作得很好(只是第一个选项的一个例子):

if @topLeftInput = 'BasicReturnReasonId'
    Begin
        Select * from test
            where BasicReturnReasonId = @topRightInput;
    End

为什么将此if语句方法更改为CASE会导致此类异常?

3 个答案:

答案 0 :(得分:0)

案例表达式的值必须仅解析为一种类型。在某些情况下,它无法返回integer,而在其他情况下则无法返回varchar。当您的可能返回值中包含混合类型时,SQL Server将选择具有最高precedence的类型。在您的案例陈述中,它是int

您必须确保所有可能的返回值都可以转换为最高优先级的类型。

答案 1 :(得分:0)

问题是案例陈述

  

从中输入类型集中的最高优先级类型   result_expressions和可选的else_result_expression

尝试像这样更改您的查询

Select  * 
from test
where 
(@topLeftInput = 'BasicReturnReasonId' and BasicReturnReasonId = @topRightInput)
or
(@topLeftInput = 'ClientName' and ClientName = @topRightInput)
or
(@topLeftInput = 'CreditDeniedReasonId' and CreditDeniedReasonId = @topRightInput)
or
(@topLeftInput = 'ItemsnotReturnedReasonId' and ItemsnotReturnedReasonId = @topRightInput)
or 
..

或者您必须明确地将integer列转换为varchar以避免隐式转换错误

CASE @topLeftInput 
                    WHEN 'BasicReturnReasonId' THEN cast(BasicReturnReasonId as varchar(50))
                    WHEN 'ClientName' THEN ClientName
                    WHEN 'CreditDeniedReasonId' THEN cast(CreditDeniedReasonId as varchar(50))
                    WHEN 'ItemsnotReturnedReasonId' THEN cast(ItemsnotReturnedReasonId as varchar(50))
                    WHEN 'ManufacturerId' THEN cast(ManufacturerId as varchar(50))
                    WHEN 'ManufacturerOrderNumber' THEN cast(ManufacturerOrderNumber as varchar(50))
                    WHEN 'ProductConditionId' THEN cast(ProductConditionId as varchar(50))
                                ELSE NULL
                    END

答案 2 :(得分:0)

根据case子句的类型优先规则,where表达式返回编译代码时确定的一种类型。

换句话说,你不能用case做你想做的事。只需使用不同的条件:

where (@topLeftInput = 'BasicReturnReasonId' AND @topRightInput = BasicReturnReasonId) or
      (@topLeftInput = 'ClientName' AND @topRightInput = ClientName) or
      . . .

出于性能原因(特别是如果你有索引),动态SQL是一种更好的方法。