在动态ORDER BY中将nvarchar转换为int时出错

时间:2014-01-02 18:23:56

标签: sql sql-server

SQL代码:

DECLARE @SortOrder nvarchar(max); 
SET @SortOrder = 'name';
SELECT * FROM [database_name].[schema_name].[table_name] 
ORDER BY CASE @SortOrder
    WHEN 'id' THEN id 
    WHEN 'name' THEN name 
    END;

输出: Msg 245,Level 16,State 1,Line 3 将nvarchar值'foo'转换为数据类型int时,转换失败。

当我改为使用@SortOrder ='id'时,它完美无缺。当我做一个普通的SELECT和ORDER BY名称时,它也可以完美地运行。

为什么会尝试将nvarchar值转换为数据类型int,如何阻止它这样做呢?

2 个答案:

答案 0 :(得分:9)

CASE是一个表达式,它返回特定数据类型的单个值。潜在值必须兼容,并且由于您必须具有foo的名称值(无法转换为INT),因此会出现此错误。解决此问题的最简单方法是按数据类型分隔ORDER BY表达式:

ORDER BY CASE @SortOrder WHEN 'id' THEN id END,
         CASE @SortOrder WHEN 'name' THEN name END;

另一种替代方案(对于计划缓存可能更好,只要你有optimize for ad hoc workloads)就是动态SQL:

DECLARE @sql NVARCHAR(MAX) = N'SELECT ... ORDER BY ' + QUOTENAME(@SortOrder) + ';';

EXEC sp_executesql @sql;

也不确定为什么要给你的@SortOrder最大数据类型 - 没有列名可能在那么大的附近。

答案 1 :(得分:-2)

通过case语句的所有路由必须输出相同的数据类型。尝试将ID转换为这样的字符串,它将起作用。

DECLARE @SortOrder nvarchar(max); 
SET @SortOrder = 'name';
SELECT * FROM [database_name].[schema_name].[table_name] 
ORDER BY CASE @SortOrder
    WHEN 'id' THEN cast(id AS NVARCHAR(20))
    WHEN 'name' THEN name 
    END;