web-dev-qa-db-ja.com

手続き型クエリが絶対に必要なのはいつですか?

SQL Server内でカーソルとループを回避する傾向があることは知っていますが、手続き型クエリが絶対に必要で、セットベースのクエリでは結果が得られない状況にはどのようなものがありますか?

私は2つの違いを理解していますが、カーソルを使用するために必要という状況になったことはありません。そんな状況があるのか​​しら。

8
Thomas Stringer

私の経験では、手続き型/反復型のアプローチが必要な場合に何度か遭遇しました。

APIは単一行の操作のみを許可します

このように500個の誤って入力された列があるテーブルでデータ型を実数から小数にプログラムで変更したい場合 SO質問 質問、DDLは変更を許可しないため、カーソルは優れたアプローチです1つのステートメントに複数の列があります。

セットベースはスケーリングしません

SQL Server MVP Deep Dives の本がある場合、第4章「セットベースの反復:3番目の選択肢」 Hugo Kornelis には、カーソルとセットを組み合わせた優れたユースケースがいくつかあります。ベースの操作。章の作成者が参照する古典的な問題の2つは、 実行中の合計ビンパッキング です。

セットベースの反復アプローチを使用して、最後のジョブで継承した設計が不十分なプロセスに成功しました。つまり、年に1回、5,000万から7,500万行を更新する必要があり、1つのセットで更新しようとすると、ログが膨大になるというプロセスがありました。更新をN行の小さなバッチにチャンク化することで、ログを維持し、実際には、1メートルトン多くのディスクスペースを割り当てた前年よりも早く終了することができました。

9
billinkc

セットベースで何かができないとき。

もちろん出血は明らかです。ただし、「セットベースではない」と手続き型ソリューションを使用する人々には違いがあることに注意してください。セットを理解していないか、セットベースのコードでそれを行う方法がわからないためです。

手続き型コードの一例は、行ごとに異なるコンテンツを持つ行ごとに電子メールを送信することです。

DBAで使用するSQLコードの多くは手続き型です。たとえば、データベースとテーブルをループ(CURSORまたはWHILE:違いなし)して、インデックスを再構築し、統計を更新します。

一部のSQL構造では、SOでのCROSS APPLYのように、セットのコンテキストで行ごとの処理が可能です。 各FKに対してTOP 5行を選択 (ただし、ROW_NUMBER()ソリューションにも注意してください)

編集:@billinkcの答えを拡張する...

CROSS APPLYにより、「単一行API」を持つUDFを使用したセットベースの操作が可能になります

6
gbn

SQL Serverについて質問されていることは知っていますが、(過去の)Oracleの世界では、一時テーブルのコストが非常に高かったため、カーソルベースのプロシージャとトリガーはサーバーにとってより迅速で低コストでした。 SQL Serverでは、カーソルのコストが一時テーブルよりもはるかに高かったため、カーソルベースのコードを作成することは推奨されていませんでした。これらの不一致は過去10年間で解消されたと確信しています。

これらの状況に対処するために、ほとんどの人はビジネスロジックをデータベースに入れないようにする一般的なルールを持っています。絶対に常にそれを行うことができれば、T-SQLでもPL/SQLでも手続き型ロジックの理由はありません。リレーショナルデータベースは、セットベースのロジックに優れています。最新のプログラミング言語のほとんどは、手続き型ロジックに優れています。それぞれが得意なものに使用するのが最善です。

私が使用したいくつかの監査トリガーには、何をチェックする必要があり、どこで更新/ログを記録する必要があるかについて、かなり複雑なルールがありました。レポートシステムをトランザクションシステムと同期させるためのものもありました(私の選択ではありませんでしたが、そのように望んでいました)。いくつかは 公式 システム用でした。処方集は薬のリストであり、各保険会社について、それらがカバーする/カバーしないもの、および処方された場合はdrug_Xが保険でカバーされる代替品です。また、同じ保険会社の異なるグループポリシーが異なる薬の支払いをすることも一般的でした。

2
Tangurena