0

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 を数値に変換中にエラーが発生しました。

誰かがこれで私を助けることができますか? 回答ありがとうございます。

4

3 に答える 3

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)また、この最後のものと一緒に使用すると、より良いプランが得られる場合があります。

于 2013-11-03T16:17:06.517 に答える
1

ケースからのすべての出力オプションは同じデータ型でなければなりません。ケースは最初のオプションから使用する出力タイプを決定し、他の値をそのタイプにキャストしようとします。あなたの場合、最初と最後のオプション、( ProductId と Price) は数値ですが、他は文字です... 次のように (両方の場所で) 大文字と小文字を変更します。

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 より前になります。

于 2013-11-03T16:18:08.323 に答える
1

CASEそれはあなたの表現のせいだと思います。ケースの最初の行はWHEN 'ProductId' THEN ProductIdであるため、他のすべてのフィールドを と同じデータ型に変換していProductIdます。Price は INT として変換できるので機能 しますが、 asでは失敗します。Price 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 列の数値と varchar 値の同じ順序を取得するために使用されます。セクションにも同じ変更を適用してくださいOrder by DESC

于 2013-11-03T16:15:00.403 に答える