2012-02-21 13 views
2

私はストアドプロシージャを呼び出し、いくつかの変数を渡す状況があります。いくつかのケースでは、私はnullで渡すだろうし、すべてを返すようにしたい。次のように入力します(年齢は整数列です)。T-SQLここで、int = @ var/@ var = null?

[Table] 
[Name] | [Age] 
Mike | 22 
Fred | 18 
Bob | 22 



SELECT * FROM [table] WHERE [Age][email protected] 

22歳で渡すと、私はマイクとボブになります。同様に18を渡すと私はフレッドを得るでしょう。しかし、nullを渡したときに3行すべてを必要とする場合、@AgeVarを設定しない場合はどうなりますか?これは私の問題です。

編集:Sprocはかなり複雑で、私は実際には以下の回答の2倍のように2つにすることによってすべてのセクションを2倍にしたくありません。他の方法はありますか?

+5

[Catch-all queries](http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/)を読む –

+2

Joe'sをクリックする時間がない場合は非常に優れた記事にリンクしているので、動的SQLを使用するとこのアプローチよりも優れたパフォーマンスを発揮する可能性があることを実証しています。 – DOK

+1

@DOK:明らかに、私は記事の著者ではない。その記事はGail Shawによって書かれました.Gail ShawはSQL Serverに関するよりもはるかに賢明です。 –

答えて

9
SELECT * FROM [table] WHERE [Age][email protected] OR @AgeVar IS NULL 

前述したように、この手法では大きなテーブルのクエリのパフォーマンスが低下します。ユーザーは注意してください。

+0

それは華麗な答えです。そのようにすることは決して考えなかった。ブリリアント。私はちょっと答えてそれに印をつけて、私は何を持っていると言います。しかし、ありがとう!! – Piercy

+8

これはちょっと参考です...これはSqlServerのQuery Execution Plansに大きな影響を及ぼしています...私たちは最近、上記のようなクエリのためにSPROCをリファクタリングしなければなりませんでした。 –

+1

@ EoinCampbell:それは私がこの質問に対する私のコメントで引用したブログ投稿のポイントです。 –

3
IF @AgeVar IS NULL 
    BEGIN 
     SELECT * 
     FROM @Table 
    END 
ELSE 
    BEGIN 
     SELECT * 
     FROM @Table 
     WHERE Age = @AgeVar 
    END 
+0

ええ、私はこのようなものを考えていたが、私はこれをやっているのですが、これは非常に巨大であり、実際には各セクションを2つの部分に分けたいのですが、他の方法はありますか? – Piercy

+0

'OR'オプションは' WHERE \t ISNULL @ [Age]、[Age])= [Age] '。しかし、上記のオプションは、オプティマイザによってうまく処理されます。ELSE'を実行した後、手順の後半でそれを参照していますが、これは残りの手順や指示などによってはさらに悪くなる可能性があります。 – GarethD

+0

これでクエリプランのキャッシュが心配です。 –

1

共通のケースがある場合は、CASE文を使用することがわかりました。これは、まれなケースでのみパフォーマンスのドラッグを行います。したがって、より頻繁にパラメータとしてnullを渡すと、より効率的になります。

SELECT * 
FROM [table] 
WHERE 
    0 = 
     CASE 
      WHEN @AgeVar IS NULL THEN 0 
      WHEN [Age][email protected] THEN 0 
     END 
+0

私は実際にこれをテストしていませんが、これはうまくいかないようです:[Age] = @AgeVarの場合、最終クエリは次のようになります。 select * from [table] 0 = 0 ...そしてあなたはすべてのレコードを取得することになります! –

+0

私はこれを多くのケースで大成功に使用しました。 SQLの仕組みについて考えてみましょう。これは理にかなっています。これは存在するものに似ています。評価されている現在の行の[Age]列が@AgeVarに等しい場合にのみ、[0] = 0の[select] from [table]が発生します。あなたのロジックによって、SQLでのマッチがまったく行われると、いつでもすべてのレコードが返されます –

1

それがインデックスではなく、インデックススキャンの追求が生成されますので、これは、あなたに[Age][email protected] OR @AgeVar IS NULL方法よりもはるかに優れた性能を提供します:

SELECT * FROM [Table1] 
WHERE COALESCE(@AgeVar, Age) = Age 

それはあなたが複数のパラメータを持っている場合は特に、かなり読みやすいコードを去りますあなたは検索に使用しているかもしれないし、使用していないかもしれないし、それでもあなたに合理的なパフォーマンスを与える。

関連する問題