web-dev-qa-db-ja.com

複数トリガーvs単一トリガー

シナリオ:

データがテーブルに挿入/更新/削除されるたびに、ビジネスロジックの関連しない複数のアイテムを実行する必要があります。

質問

ソリューションがデータベーストリガーを使用することであるとすると、どのオプションが優れていますか?:

1)操作ごとに1つのトリガー(挿入/更新/削除):

  • I_Table-挿入時に実行されます
  • U_Table-更新時に実行されます
  • D_Table-削除時に実行されます

各トリガーは、ビジネスロジックの関連しない複数のアイテムを処理します。

OR

2)懸念事項によって分離された操作ごとの複数のトリガー:

  • I_Table_Logging-挿入時のログ用
  • I_Table_RI-挿入時に参照整合性を適用します
  • I_Table_BL-挿入時にビジネスロジックを実行するため
  • U_Table_Logging-アップデートのログオン用
  • U_Table_RI-更新時に参照整合性を適用するため
  • U_Table_BL-更新時にビジネスロジックを実行するため
  • D_Table_Logging-削除のログオン用
  • D_Table_RI-削除時に参照整合性を適用します
  • D_Table_BL-削除時にビジネスロジックを実行するため

単一のコード単位に単一の懸念があるため、私はオプション2を好みます。私はDBAではありません。SQLServerについて十分に理解しているので、危険です。

データベースのアーキテクチャとスキーマは変更しないでください。スキーマには明示的な関係を適用する必要がある場所がいくつかありますが、残念ながらまだ変更できません。これが、明示的な関係に依存するのではなく、参照整合性を手動で適用する必要がある理由です。

すべての懸念事項を1つのトリガーで処理する説得力のある理由はありますか?特に、パフォーマンス、実行の順序、およびロールバックに関心があります。

5
Dan

私の個人的な好みは、DML操作ではなく、機能ごとにトリガーを作成することです。したがって、私は挿入/更新/削除の監査を処理するもの、ある種のビジネスルールまたは参照整合性を実行する(挿入/更新/削除の)もの、クライアントソフトウェアの望ましくない動作を回避するために醜いハッキングを実行するものがあります(おそらく挿入または更新のみ)など.

各「動作」を1か所に保持することで、3つの個別の挿入、更新、および削除トリガー間で複製されたロジックの更新を忘れる可能性が低くなります。

トリガーの最大の落とし穴は、INSERTEDテーブルとDELETEDテーブルにインデックスが付けられていないことであり、それらに直接インデックスを付けることはできません。大きなデータセットに対してそれらを結合することは恐ろしく実行され、テーブルに多くのトリガーがある場合、特にトリガーカスケードが作用し始めると、事態は本当に手に負えなくなります。

私が作成するほとんどのトリガーは、必要となるINSERTEDおよびDELETEDの列を使用してテーブル変数@iおよび@dを作成し、クラスター化された主キーの両方を提供することで開始します(これがテーブル変数にインデックスを付ける唯一の方法であるため)。 INSERTEDおよびDELETEDからのデータを含む。

私はトリガーについての短い(非営利的な)記事を書きました、そしてそれはまたいくつかの他のポイントをカバーします。

http://dave.brittens.org/2012/03/29/writing-well-behaved-triggers/

6
db2

私はこれを十分に強調することはできません:トリガーはビジネスロジックの場所ではありません!

監査目的でのみトリガーを使用します(たとえば、最終更新日付スタンプ)。トリガー内にビジネスロジックを配置することは、最初は良い考えのように思えるかもしれませんが、将来的には何度も何度も何度も何度も自分自身を撃つことになるでしょう。トリガーは忘れられがちで、後日実行する必要のある他の一括操作に干渉し始めます。何度も何度もこの状況が発生し、不幸な不幸なDBAが「GAH!私はこれらすべてのトリガーを忘れてしまった」と叫びました。

ビジネスロジックをアプリケーション、または少なくともデータ操作を行うストアドプロシージャに移動します。トリガーはそのための場所ではありません。制約を使用して、トリガーではなくデータの整合性を適用します。

6
datagod