質問

私はこれまで、データベース テーブルでトリガーを使用するのが好きではありませんでした。私にとって、それらは常に、アプリケーション コードの制御から遠く離れたデータベース側で起こるであろう何らかの「魔法」を表していました。また、DB は一般的に共有リソースであり、高負荷のシナリオではトリガーのコストが高くなる可能性があると常々思っていたため、DB が実行する必要がある作業量を制限したいと考えていました。

そうは言っても、トリガーを使用するのが理にかなっている (少なくとも私の意見では、トリガーは理にかなっている) 例をいくつか見つけました。しかし最近、私は時々トリガーを「バイパス」する必要があるかもしれない状況に陥っていることに気づきました。私はこれを行う方法を探さなければならないことに本当に罪悪感を感じていましたが、データベース設計を改善すれば、このバイパスの必要性が軽減されるだろうと今でも思っています。残念ながら、この DB は複数のアプリケーションで使用されており、その一部はスキーマの変更について叫ぶ非常に非協力的な開発チームによって保守されているため、行き詰まってしまいました。

トリガーについての一般的なコンセンサスは何ですか?好きですか?嫌いですか?いくつかのシナリオではそれらが目的を果たすと思いますか?トリガーをバイパスする必要があるということは、「間違ったことをしている」ことを意味すると思いますか?

役に立ちましたか?

解決

トリガーは通常、誤って使用され、バグを引き起こすため、使用しないでください。テーブル内の行をまたがる整合性制約チェックを行うトリガーを決して設計しないでください (例: 「部門別の平均給与は X を超えることはできません)」。

トム・カイト, 、Oracle の副社長は、次のことを希望すると述べています。 Oracle の機能としてトリガーを削除する データベースはバグに頻繁に関与するためです。彼は、これが単なる夢であり、トリガーは今後も存続することを知っていますが、できることなら Oracle からトリガーを削除したいと考えています (WHEN OTHERS 句と自律型トランザクションとともに)。

トリガーは正しく使用できますか?絶対に。

問題は、多くの場合に正しく使用されていないため、それらによって引き起こされた虐待(およびバグ)を取り除くためだけに、知覚された利益をあきらめることをいとわないことです。- トム・カイト

他のヒント

データベースを大きな大きなオブジェクトとして考えてください。データベースを呼び出すたびに、論理的に一貫した状態になる必要があります。

データベースはテーブルを介してデータベース自体を公開し、テーブルと行の一貫性を保つにはトリガーを使用できます。一貫性を保つもう 1 つの方法は、テーブルへの直接アクセスを禁止し、ストアド プロシージャとビュー経由のみを許可することです。

トリガーの欠点は、どのアクションでもトリガーを呼び出すことができることです。これは強みでもあります。無能によってシステムの完全性を台無しにする人は誰もいません。

反対に、ストアド プロシージャとビューを通じてのみデータベースへのアクセスを許可しても、アクセス許可のバックドア アクセスは許可されます。十分な権限を持つユーザーはデータベースの整合性を壊さないと信頼されており、その他のユーザーはストアド プロシージャを使用します。

仕事量の削減に関しては、次のようになります。データベースは、外部の世界とやり取りする必要がない場合、驚くほど効率的です。プロセスの切り替えだけでもパフォーマンスがどれほど低下するかには本当に驚かれるでしょう。これもストアド プロシージャの利点です。データベースへの 12 回の呼び出し (および関連するすべての往復) ではなく、1 回の呼び出しです。

単一のストアド プロシージャに内容をまとめることは問題ありませんが、何か問題が発生した場合はどうなるのでしょうか?5 つのステップがあり、最初のステップが失敗した場合、他のステップはどうなるのでしょうか?その状況に対応するには、そこに大量のロジックを追加する必要があります。これを開始すると、そのシナリオではストアド プロシージャの利点が失われます。

ビジネス ロジックはどこかに配置する必要があり、データベースの設計には多くの暗黙のドメイン ルールが埋め込まれています。関係や制約などは、たとえばユーザーが持つことができるパスワードは 1 つだけであるなど、ビジネス ルールを成文化しようとする試みです。これらの関係などを持たせることでビジネス ルールをデータベース サーバーに押し付け始めたとすると、どこに線を引くのでしょうか?データベースはいつデータの整合性に対する責任を放棄し、呼び出し元のアプリやデータベース ユーザーが正しくデータを取得することを信頼し始めるのでしょうか?これらのルールが埋め込まれたストアド プロシージャは、多くの政治的権力を DBA の手に押し付ける可能性があります。結局のところ、n 層アーキテクチャにいくつの層が存在するかによって決まります。プレゼンテーション、ビジネス、データのレイヤーがある場合、ビジネスとデータの分離はどこにあるのでしょうか?ビジネス層はどのような付加価値をもたらしますか?ビジネス層をデータベース サーバー上でストアド プロシージャとして実行しますか?

はい、トリガーをバイパスしなければならないということは、「間違ったことをしている」ことを意味すると思います。この場合、トリガーはあなたには適していません。

enter image description here

私は C# で Web アプリと winforms アプリを操作しています。 嫌い 情熱を持ってトリガーします。私は、ロジックをアプリケーションのビジネス層に移動し、そこでトリガー ロジックを複製することよりも、トリガーの使用を正当化できる状況に遭遇したことがありません。

私は DTS タイプの作業などは一切行っていないので、そこでトリガーを使用するユースケースがいくつかあるかもしれませんが、私のチームの誰かがトリガーを使用したいかもしれないと言ったら、議論を十分に準備した方がよいでしょう。なぜなら、私は作業中のデータベースにトリガーを追加させたり、待機したりすることを拒否するからです。

私がトリガーを好まない理由は次のとおりです。

  • ロジックをデータベースに移動します。一度それをやり始めると、デバッグ、コンパイル時の安全性、ロジック フローが失われるため、苦痛の世界を求めることになります。それはすべて下り坂です。
  • 彼らが実装するロジックは誰にも簡単には見えません。
  • すべてのデータベース エンジンがトリガーをサポートしているわけではないため、ソリューションではデータベース エンジンへの依存関係が作成されます。

もっと他にも理由が思いつくと思いますが、トリガーを使用しない理由としてはこれだけでも十分です。

「テーブル内の行をまたがる整合性制約チェックを行うトリガーを決して設計しないでください」 -- 私は同意できません。この質問には「SQL Server」というタグが付いていますが、SQL Server の CHECK 制約句にはサブクエリを含めることはできません。さらに悪いことに、実装では CHECK には 1 つの行のみが含まれるという「ハードコードされた」前提があるようで、関数の使用は信頼できません。したがって、正当に複数の行を含む制約が必要な場合、その良い例が、同じエンティティの期間の重複を防ぐ必要がある、古典的な「有効時間」テンポラル テーブルの順序付けされた主キーです。トリガーなしでそれを行うのですか?これは主キーであり、データの整合性を確保するためのものであるため、DBMS 以外の場所で強制することは問題外であることに注意してください。CHECK 制約がサブクエリを取得するまでは、特定の種類の整合性制約にトリガーを使用する代替手段は見つかりません。

トリガーは非常に役立ちます。非常に危険な場合もあります。監査データ (作成者、変更日など) を入力するようなハウスクリーニングタスクには適していると思います。また、一部のデータベースでは参照整合性のために使用できます。

しかし、私はそこに多くのビジネス ロジックを組み込むのがあまり好きではありません。これにより、次の理由からサポートに問題が生じる可能性があります。

  • 調査する必要がある追加のコード層です
  • OP が学んだように、データ修正を行う必要がある場合、トリガーは、データ変更が常にアプリケーション ディレクティブ経由であり、問​​題を修正する開発者や DBA からではなく、さらには別のディレクティブからのものであるという前提で処理を行っている可能性があります。アプリ

何かをするためにトリガーをバイパスする必要があるということに関しては、それはあなたが何か間違ったことをしていることを意味するかもしれませんし、トリガーが何か間違ったことをしていることを意味するかもしれません。

私がトリガーで使用する一般的なルールは、トリガーを軽量、高速、シンプル、そして可能な限り非侵襲的なものにすることです。

一括データのインポートを行うときにトリガーをバイパスしていることに気づきました。このような状況では正当化されると思います。

ただし、トリガーを頻繁にバイパスしてしまう場合は、そもそもトリガーを何のために配置したかをもう一度検討する必要があります。

一般的に、私は「いくつかのシナリオでは目的を果たす」に投票します。私はパフォーマンスへの影響について常に不安を感じています。

個人的にはファンではありません。これらを使用するのは、アクションをトリガーに移動することで解決できるコード内のボトルネックが見つかった場合のみです。一般に、私はシンプルさを好みます。物事をシンプルに保つ 1 つの方法は、ロジックを 1 か所 (アプリケーション) に保持することです。私は、アクセスが非常に細分化されている仕事にも取り組んできました。このような環境では、トリガーに詰め込むコードが増えるほど、最も単純な修正であっても、より多くの人を関与させる必要があります。

数週間前に初めてトリガーを使用しました。運用サーバーを SQL 2000 から SQL 2005 に切り替えたところ、ドライバーが NText フィールド (大きな XML ドキュメントを保存する) で異なる動作をし、最後のバイトが欠落していることがわかりました。一時的な修正としてトリガーを使用して、データの末尾に追加のダミー バイト (スペース) を追加し、適切な解決策が展開されるまで問題を解決しました。

この特殊な一時的なケースを除けば、私はそれらを避けると思います。なぜなら、それらは何が起こっているかを隠蔽し、それらが提供する機能は、隠された魔法としてではなく、開発者によって明示的に処理されるべきだからです。

正直に言うと、一意性を考慮しない NULL を許可する一意のインデックスをシミュレートするためにトリガーを使用するのは 1 回だけです。

仕事量の削減に関しては、次のようになります。データベースは、外部の世界とやり取りする必要がない場合、驚くほど効率的です。プロセスの切り替えだけでもパフォーマンスがどれほど低下するかには本当に驚かれるでしょう。これもストアド プロシージャの利点です。データベースへの 12 回の呼び出し (および関連するすべての往復) ではなく、1 回の呼び出しです。

これは少し本題から外れましたが、これを 1 つの潜在的なポジティブな側面からのみ見ていることにも注意する必要があります。

単一のストアド プロシージャに内容をまとめることは問題ありませんが、何か問題が発生した場合はどうなるのでしょうか?5 つのステップがあり、最初のステップが失敗した場合、他のステップはどうなるのでしょうか?その状況に対応するには、そこに大量のロジックを追加する必要があります。これを開始すると、そのシナリオではストアド プロシージャの利点が失われます。

トータルファン、

しかし、本当に慎重に使用する必要がある場合は、

  • 一貫性を維持する必要があります (特にディメンション テーブルがウェアハウスで使用されており、ファクト テーブル内のデータを適切なディメンションに関連付ける必要がある場合)。場合によっては、ディメンション テーブル内の適切な行の計算に非常にコストがかかるため、キーをファクト テーブルに直接書き込む必要がある場合があります。その「関係」を維持するための 1 つの良い方法は、トリガーを使用することです。

  • 変更をログに記録する必要があります (たとえば、監査テーブルでは、@@user がどのような変更を行ったのか、いつ変更が行われたのかを知ると便利です)

SQL Server 2005 などの一部の RDBMS では、CREATE/ALTER/DROP ステートメントでのトリガーも提供されます (そのため、誰がどのテーブルをいつ作成し、どの列をドロップしたかなどを知ることができます)。

正直なところ、これら 3 つのシナリオでトリガーを使用する場合、なぜトリガーを「無効にする」必要があるのか​​わかりません。

一般的な経験則は次のとおりです。トリガーは使用しないでください。前に述べたように、オーバーヘッドと複雑さが追加されますが、ロジックを DB 層の外に移動することで簡単に回避できます。

また、MS SQL Server では、トリガーは行ごとではなく SQL コマンドごとに 1 回起動されます。たとえば、次の SQL ステートメントはトリガーを 1 回だけ実行します。

UPDATE tblUsers
SET Age = 11
WHERE State = 'NY'

私を含む多くの人は、トリガーはすべての行で起動されるものだと思い込んでいますが、そうではありません。複数の行のデータを変更する可能性のある上記のような SQL ステートメントがある場合は、トリガーの影響を受けるすべてのレコードを更新するカーソルを含めることができます。これがいかに急速に複雑になるかがわかります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top