2009-07-17 10 views
2

ストアドプロシージャ内では、アイテムのテーブル(#Items)を設定します。それらに関する基本的な情報しかし、それぞれの商品について、私はそれらを販売することができることを確認する必要があります。そのためには、多くのバリデーションを実行する必要があります。ストアドプロシージャをいくらか保守可能にするために、私はそのロジックを別のストアドプロシージャに移しました。このSQLロジックを処理するにはどうすればよいでしょうか?

一時テーブルの各アイテムのストアドプロシージャを呼び出すにはどうすればよいでしょうか?

私は今、ID列を適用し、whileループを実行して、各行のストアドプロシージャを実行し、検証結果を一時テーブルに挿入します。 (#Validation)

しかし、今度はロジックが変更され、#Itemの作成とループの実行の間に、IDがもはやカウンタに等しくないため、whileループを壊すレコードが削除されます。

アイデンティティ列を削除してwhileループの前にそれを適用することでそれを処理できますが、より良い方法があるかどうかは疑問でした。 order by節を適用すると、インデックスに特定の行を取得する方法はありますか?

私はカーソルを使うことができると知っていますが、それらは私にとっては痛みです。また、パフォーマンスはいくらか懸念されますが、早送りの読み込みカーソルはwhileループよりも優れたオプションですか? #Itemsテーブルの行数はそれほど大きくなく、おそらく最大で50ですが、ストアドプロシージャはかなり頻繁に呼び出されます。

答えて

3
    は、アイテムIDを受け入れるか、アイテムレコード
  1. を検証するために必要なデータ列を一時テーブル
  2. を作成し、ユーザー定義関数にあなたの検証ストアドプロシージャを回し
  3. すべてのアイテム
  4. 書き込みaを挿入しますWHERE句で新しいUDFを呼び出す一時テーブルのクエリを削除します。
+0

ありがとう、これは素晴らしい動作するはずです。私はユーザー定義関数に慣れていませんが、これはコストパフォーマンスの高い賢明なものになるでしょうか? – Brandon

+1

アイテムを手作業でループする以上のことはありません。通常、すべてのロジックをwhere句に入れることでそれを改善できますが、それは読み込み/保守がさらに難しくなります。この場合、一時テーブルにはおそらくインデックスがないため、あまり役に立ちません。 –

+1

ユーザ定義関数はsprocsと非常によく似ていますが、いくつかの異なる制限/機能があります。 OKを実行する必要があります(ループよりもはるかに優れたセットベース)。実行計画がキャッシュ/再利用されていることから利益を得ます。 – AdaTheDev

1

このようなビジネスロジックは、実際にデータベースに存在する必要がありますか? あなたのシナリオについてはよくわかりませんが、SPでモデル化しようとしているその決定をアプリケーションに移行するのが最善でしょうか?

そのロジックのストアドプロシージャの代わりに関数を使用し、この関数の結果をテンポラリテーブルの列として含めることもできます。それはあなたのために働くだろうか?または、後で使用するたびにデータをリアルタイムで必要とする場合、選択リストに含まれる0/1の値を返す関数は、とにかくうまくいく可能性があります。

+0

私を信頼してください、私はかなりコードでこれを行うでしょう。しかし、私はその選択肢を持っていません。 – Brandon

+0

+1の機能の提案です。 – Brandon

0

クエリを使用してストアドプロシージャロジックを書き直すことができる、 私。 e。セットベースのアプローチ?

まずこれを試してください。

+0

検証ストアドプロシージャまたはメインストアドプロシージャを参照していますか?また、検証SPから大量のロジックをメインSPに移行するのとは別に、これをセットベースのアプローチに変更する方法についてもわかりません。 – Brandon

2

私はあなたがそれをセットベースで行うことができれば、そのようにすることに同意します。おそらく、バリデーションを有効にするために、sprocの代わりにユーザ定義関数にバリデーションを入れてください。どのかもしれないあなたがそれをセットベースで行うことができる方法を舗装する。

SELECT * FROM SomeTable WHERE dbo.fnIsValid(dataitem1, dataitem2....) = 1 

ただし、実際のシナリオによってはこれが可能でない可能性があります。今IDENTITY /ループ問題を理解することに基づいて

修正編集: あなたは、次の行を取得するために、SQL 2005でROW_NUMBER()を使用することができ、これが割り当てられますように隙間がIDENTITYフィールドであるかどうかは問題ではありません。あなたがそれ言うものによって命じ各レコードに行番号: は - 次のレコード SELECT * (ROWNO AS OVER SELECT ROW_NUMBER()(IDFieldのASC BY ORDER)、* #temptable から)の WHEREを取得します。 s.RowNo = @Counter

+0

whileループでは、@counterに基づいてどのように行を選択しますか?私が注文を適用した場合、基本的にインデックスである行に基づいてアクセスする方法はありますか? – Brandon

+0

ああ私は誤解しました。ループ内の各行を取得する代わりにROW_NUMBER()を使用して、 – AdaTheDev

+0

+1を説明する解答を編集します。ユーザー定義の提案に行ってきました。 – Brandon

関連する問題