0

这是我的存储过程

 [sp_Get_Data]
   (
   @IdParam INT, 
   @OrderBy varchar(50),
   @Direc varchar(4),
   )
 AS
 BEGIN
select 
   [LogID] //int
  ,[Address]   //varchar
  ,[State]    //varchar
  ,[City]
  ,[Zip]
  FROM LogData 
WHERE IdParam = LogID
order by 

  CASE @Direc 
    WHEN 'desc' THEN  
    CASE @OrderBy 
        WHEN 'LogID' THEN LogID 
        WHEN 'Address' THEN Address
        END 
    END 
    DESC, 
CASE @Direc 
    WHEN 'asc' THEN              
    CASE @OrderBy 
        WHEN 'LogID' THEN LogID 
        WHEN 'Address' THEN Address
        END 
    END 

EXEC [sp_Get_Data] @IdParam ='..' @OrderBy = 'LogID', @Direc = 'asc'   // WORKS FINE
EXEC [sp_Get_Data] @IdParam ='..' @OrderBy = 'Address', @Direc = 'asc'

错误:

将 varchar 值“xyz”转换为数据类型 int 时转换失败。

如果我通过,而不是使用这个动态参数进行排序

ORDER BY Address ASC ....

这行得通。

我在这里缺少一些非常基本的东西吗?

4

2 回答 2

2

CASE 的返回值类型应该相同。在第一种情况下,它没有到达地址,所以它可以工作。但是对于“地址”,它期望与作为 int 的 LogId 相同。所以转换失败。

注意: 转换LogIdVARCHAR类型会将错误排序but it would not give you correct ordering为数字。所以使用该RIGHT功能来解决它

RIGHT(REPLICATE('0',11) + CONVERT(VARCHAR(50),LogID), 12)

这里是演示

SELECT * FROM T
ORDER BY 
   CASE @Direc 
    WHEN 'desc' THEN  
    CASE @OrderBy 
        WHEN 'LogID' THEN RIGHT (REPLICATE('0',11) + CONVERT(VARCHAR(50),LogID), 12)
        WHEN 'Address' THEN Address
        END 
    END 
    DESC, 
CASE @Direc 
    WHEN 'asc' THEN              
    CASE @OrderBy 
        WHEN 'LogID' THEN RIGHT (REPLICATE('0',11) + CONVERT(VARCHAR(50),LogID), 12)
        WHEN 'Address' THEN Address
        END 
    END 
于 2013-01-24T19:37:34.987 回答
1

问题是您的第一次执行(使用LogID)使用INT. 执行第二次调用时,预编译的执行计划遇到了数据转换异常。

一种解决方案是强制LogID转换为一种VARCHAR类型,以便始终遇到相同的数据类型:

(...)

CASE @Direc 
WHEN 'desc' THEN  
CASE @OrderBy 
    WHEN 'LogID' THEN CONVERT(VARCHAR(50), LogID)
    WHEN 'Address' THEN Address
    END 
END 
DESC, 
CASE @Direc 
WHEN 'asc' THEN              
CASE @OrderBy 
    WHEN 'LogID' THEN CONVERT(VARCHAR(50), LogID)
    WHEN 'Address' THEN Address
    END 
END 

(...)

但是,通常这种操作 ( ORDER BY) 是在应用程序端完成的......除非您可以证明这种方法具有显着的性能改进。我只是想确定你知道你在做什么。

注意:您可以尝试OPTION (RECOMPILE)在存储过程的末尾使用而不要使用CONVERT,因为每次使用后都会重新编译执行计划。CONVERT在每次执行后重新编译存储过程而不是使用所有这些//调整可能要求不高RIGHTREPLICATE你会看到的。

于 2013-01-24T19:33:56.213 回答