web-dev-qa-db-ja.com

列名のパラメーターを使用した「並べ替え」

Visual Studio DataSet Designerで作成されたクエリまたはストアドプロシージャの "Order By"句でパラメーターを使用します。

例:

  FROM TableName
 WHERE (Forename LIKE '%' + @SearchValue + '%') OR
       (Surname LIKE '%' + @SearchValue + '%') OR
       (@SearchValue = 'ALL')
ORDER BY @OrderByColumn

このエラーは表示されます:

Variables are only allowed when ordering by an expression referencing 
a column name.
20
Emad-ud-deen

次のようなことができるはずです。

SELECT *
FROM
    TableName
WHERE
    (Forename LIKE '%' + @SearchValue + '%') OR
    (Surname LIKE '%' + @SearchValue + '%') OR
    (@SearchValue = 'ALL')
ORDER BY 
    CASE @OrderByColumn
    WHEN 1 THEN Forename
    WHEN 2 THEN Surname
    END;
  • Forenameでソートするには、@OrderByColumnに1を割り当てます。
  • Surnameでソートするには2を割り当てます。
  • その他...このスキームを任意の列数に拡張できます。

ただし、パフォーマンスには注意してください。これらの種類のコンストラクトは、クエリオプティマイザーが最適な実行プランを見つける能力を妨げる可能性があります。たとえば、Forenameがインデックスでカバーされている場合でも、クエリは単にインデックスを順番にたどるのではなく、完全な並べ替えを必要とする場合があります。

その場合、パフォーマンスへの影響に耐えられない場合は、可能な並べ替え順序ごとに個別のバージョンのクエリを用意する必要があり、クライアント側でかなり複雑になります。

43

私はこのスレッドに遅れて来ていることを知っていますが、他の誰かが同様の問題を抱えている場合に備えてこれを投稿したいだけです。

この問題は、パラメータに対して_ORDER BY_を直接実行しようとすると発生するようです。これは、SQL Serverが番号(最初のフィールドに1、2番目に2など)を提供することを期待しているためです。または、識別子(MyFieldまたは "MyField")または文字列( 'MyField')として表示される列名。

例えば:

_DECLARE @ORDERBY AS NVARCHAR(20)
;

SELECT @ORDERBY = :Param1 --(Supposing that the user enters 'MyField')
;

SELECT TOP 1 *
FROM MyTable
ORDER BY @ORDERBY DESC
;
_

次のエラーが表示されます。

ORDER BY番号1で識別されるSELECTアイテムには、列の位置を識別する式の一部として変数が含まれています。変数は、列名を参照する式で並べ替える場合にのみ許可されます。 (SQLSTATE = 42000)(1008)(重大度= 16)

説明した方法のいずれか(クエリまたは識別子を使用)でクエリを手動で記述した場合、エラーはありません。

_SELECT TOP 1 *
FROM MyTable
ORDER BY MyField DESC
;

SELECT TOP 1 *
FROM MyTable
ORDER BY "MyField" DESC
;

SELECT TOP 1 *
FROM MyTable
ORDER BY 'MyField' DESC
;
_

そのため、同じパラメーターでCAST()を実行すると、その値は文字列に変換され、クエリは正常に実行されます。

_DECLARE @ORDERBY AS NVARCHAR(20)
;

SELECT @ORDERBY = :Param1 --(Supposing that the user enters the text 'MyField')
;

SELECT TOP 1 *
FROM MyTable
ORDER BY CAST(@ORDERBY AS NVARCHAR(20)) DESC
;
_

この場合(再び、ユーザーが文字列 'MyField'を:Param1の値として書き込んだと仮定すると)、実行される実際のクエリは次のようになります。

_SELECT TOP 1 *
FROM MyTable
ORDER BY 'MyField' DESC
;
_

このクエリは正常に実行されます。エラーが発生せず、パフォーマンスへの明らかな重大な影響もありません。すべての可能なユーザー入力をCASEステートメントに列挙する必要はありません。

2005年から2016年までMicrosoft SQL Serverでこのソリューションを何度も使用しましたが、何の問題もありません。

うまくいけば、これはまだ誰かに役立つことができます。

1
3BK