存储过程和错误数据类型nvarchar为numeric

时间:2013-11-03 16:07:43

标签: sql sql-server tsql stored-procedures

我在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转换为数字时出错。

有人可以帮我这个吗?谢谢你的回答。

3 个答案:

答案 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之前完成