我在SQL Server 2012中遇到了存储过程的问题。
首先是表格:
[ProductId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
[Description] [nvarchar](500) NOT NULL,
[Category] [nvarchar](50) NOT NULL,
[Price] [decimal](16, 2) NOT NULL,
和存储过程:
CREATE procedure [dbo].[GetProductsPaging]
(@PageOffset bigint=0,
@PageSize bigint=5,
@OrderBy varchar(30) = 'ProductId',
@DescOrder bit = 0)
AS
BEGIN
IF @DescOrder = 0
BEGIN
SELECT * FROM [dbo].Products
ORDER BY
CASE @OrderBy
WHEN 'ProductId' THEN ProductId
WHEN 'Name' THEN Name
WHEN 'Category' THEN Category
WHEN 'Price' THEN Price
ELSE NULL
END ASC
OFFSET @PageOffset ROWS
FETCH NEXT @PageSize ROWS ONLY
END
ELSE
BEGIN
SELECT * FROM [dbo].Products
ORDER BY
CASE @OrderBy
WHEN 'ProductId' THEN ProductId
WHEN 'Name' THEN Name
WHEN 'Category' THEN Category
WHEN 'Price' THEN Price
ELSE NULL
END DESC
OFFSET @PageOffset ROWS
FETCH NEXT @PageSize ROWS ONLY
END
END
当我像这样执行时
EXEC dbo.GetProductsPaging 0, 0 ,'Price', 0
程序运行正常,但在使用时
EXEC dbo.GetProcedurePaging 0, 0, 'Name', 0
我收到此错误
将数据类型nvarchar转换为数字时出错。
有人可以帮我这个吗?谢谢你的回答。
答案 0 :(得分:1)
我认为这是因为你的CASE
表达式。您的案例的第一行是WHEN 'ProductId' THEN ProductId
,因此它将每个其他字段转换为与ProductId
相同的数据类型。它适用于 Price
,因为Price可以转换为INT,但 Name
的 it encounters an error converting data type nvarchar to numeric
尝试此操作可获得相同的结果:
CASE @OrderBy
WHEN 'ProductId' THEN RIGHT(100000000 + ProductId, 8)
WHEN 'Name' THEN Name
WHEN 'Category' THEN Category
WHEN 'Price' THEN RIGHT(100000000 + Price, 8)
ELSE NULL
END ASC
Right()
函数用于获取ProductId和Price列的numeric和varchar值的相同顺序。请对Order by DESC
部分应用相同的更改。
答案 1 :(得分:1)
ORDER BY
CASE @OrderBy
WHEN 'ProductId' THEN ProductId
WHEN 'Name' THEN Name
WHEN 'Category' THEN Category
WHEN 'Price' THEN Price
ELSE NULL
END ASC
混合数字和非数字分支时,不起作用。 CASE
表达式的类型是具有最高数据类型优先级的分支的类型。你可以使用
ORDER BY
CASE @OrderBy
WHEN 'ProductId' THEN ProductId
WHEN 'Name' THEN Name
WHEN 'Category' THEN Category
WHEN 'Price' THEN Price
ELSE CAST(NULL AS SQL_VARIANT)
END ASC
或
ORDER BY CASE
WHEN 'ProductId' = @OrderBy THEN ProductId
END,
CASE
WHEN 'Name' = @OrderBy THEN Name
END,
CASE
WHEN 'Category' = @OrderBy THEN Category
END,
CASE
WHEN 'Price' = @OrderBy THEN Price
END
如果你使用最后一个OPTION (RECOMPILE)
,你可能会得到一个更好的计划。
答案 2 :(得分:1)
案例中的所有输出选项必须具有相同的数据类型,我认为案例决定从第一个选项中使用哪种输出类型,并尝试将其他值转换为该类型,在您的情况下,第一个和最后一个选项,(ProductId和Price)是数字,其他是buit ...修改案例(在两个地方)如下:
CASE @OrderBy
WHEN 'ProductId' THEN str(ProductId, 7, 0)
WHEN 'Name' THEN Name
WHEN 'Category' THEN Category
WHEN 'Price' THEN str(Price, 16,4)
ELSE NULL
END ASC
然而,意识到价格的任何分类现在都将以字符为基础进行,即100将在20之前完成