我正在使用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
@topLeftInput
为ClientName
或ManufacturerOrderNumber
时发生异常。当@topLeftInput
等于其中任何一个时,用户可以在文本框中输入@topRightInput
的值,而不是使用下拉列表。
我收到一个异常,说明将varchar值转换为int时出错。不确定为什么要这样做。
在我之前使用的技术中,这个例外并没有发生,并且它工作得很好(只是第一个选项的一个例子):
if @topLeftInput = 'BasicReturnReasonId'
Begin
Select * from test
where BasicReturnReasonId = @topRightInput;
End
为什么将此if语句方法更改为CASE
会导致此类异常?
答案 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是一种更好的方法。