18

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

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

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

4

12 に答える 12

12

トリガーは一般的に誤って使用され、バグが発生するため、回避する必要があります。テーブル内の行と交差する整合性制約チェックを実行するトリガーを設計しないでください(たとえば、「部門別の平均給与はXを超えることはできません)。

OracleのVPであるTomKyteは、バグで頻繁に発生するため、Oracleデータベースの機能としてトリガーを削除することを希望していると述べています。彼はそれが単なる夢であることを知っており、トリガーはここにとどまりますが、オラクルからトリガーを削除できれば、(WHEN OTHERS句と自律トランザクションとともに)そうします。

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

問題は、それらが正しく使用されていないため、それらによって引き起こされた乱用(およびバグ)を取り除くためだけに、認識された利益を放棄することをいとわないということです。-トム・カイト

于 2008-08-18T03:23:39.497 に答える
9

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

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

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

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

作業量の削減に関して: データベースは、外部の世界を処理する必要がない場合、驚くほど効率的です。プロセスの切り替えでさえパフォーマンスがどれだけ低下するかに本当に驚かれることでしょう。これは、ストアド プロシージャのもう 1 つの利点です。データベースへの多数の呼び出し (および関連するすべてのラウンド トリップ) ではなく、1 回です。

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

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

はい、トリガーをバイパスする必要があるということは、「間違ったことをしている」ことを意味すると思います。この場合、トリガーはあなたのためではありません。

ここに画像の説明を入力

于 2008-08-18T00:37:45.760 に答える
2

「テーブルの行と交差する整合性制約チェックを実行するトリガーを設計しないでください」-同意できません。質問には「SQLServer」というタグが付けられており、SQLServerの「CHECK制約」句にサブクエリを含めることはできません。さらに悪いことに、実装には、CHECKが単一の行のみを含むという「ハードコーディングされた」仮定があるように思われるため、関数の使用は信頼できません。したがって、合法的に複数の行を含む制約が必要な場合-そしてここでの良い例は、同じエンティティの期間の重複を防ぐ必要がある古典的な「有効時間」時間テーブルのシーケンスされた主キーです-どうすればよいですか?私はトリガーなしでそれをしますか?これは主キーであり、データの整合性を確保するためのものであるため、DBMS以外の場所で強制することは問題外です。

于 2008-10-14T19:38:45.357 に答える
2

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

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

トリガーが嫌いな理由は次のとおりです。

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

頭のてっぺんからもっと多くの理由を考えることができると確信していますが、それらだけでトリガーを使用しないのに十分です.

于 2008-08-18T00:08:53.853 に答える
2

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

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

  • 調査するコードの追加レイヤーです
  • OPが学んだように、データの修正を行う必要がある場合、トリガーは、データの変更は常にアプリケーションディレクティブを介して行われ、開発者やDBAが問題を修正したり、別のアプリ

何かを行うためにトリガーをバイパスする必要がある場合は、何か間違ったことをしている、またはトリガーが何か間違っていることを意味している可能性があります。

私がトリガーで使用する一般的なルールは、トリガーを軽量、高速、シンプル、かつできるだけ非侵襲的に保つことです。

于 2008-08-18T00:18:13.863 に答える
1

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

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

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

于 2008-08-18T00:13:45.310 に答える
0

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

于 2008-08-18T00:09:32.510 に答える
0

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

この特別な一時的なケース以外では、何が起こっているのかを隠してしまうので避けたいと思います。それらが提供する機能は、隠された魔法としてではなく、開発者が明示的に処理する必要があります。

于 2008-08-18T00:30:46.210 に答える
0

正直なところ、一意性にカウントされない NULL を持つことが許可されている一意のインデックスをシミュレートするためにトリガーを使用するのは一度だけです。

于 2008-08-18T00:40:58.123 に答える
0

作業量の削減に関して: データベースは、外部の世界を処理する必要がない場合、驚くほど効率的です。プロセスの切り替えでさえパフォーマンスがどれだけ低下するかに本当に驚かれることでしょう。これは、ストアド プロシージャのもう 1 つの利点です。データベースへの多数の呼び出し (および関連するすべてのラウンド トリップ) ではなく、1 回です。

これは少し話題から外れていますが、これは 1 つの潜在的なポジティブな点からしか見ていないことに注意してください。

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

于 2008-08-18T01:01:10.017 に答える
0

完全なファン、

しかし、実際には控えめに使用する必要があり、

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

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

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

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

于 2008-08-18T01:32:48.143 に答える
0

一般的な経験則は、トリガーを使用しないことです。前述のように、ロジックを DB レイヤーから移動することで簡単に回避できるオーバーヘッドと複雑さが追加されます。

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

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

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

于 2008-08-18T19:08:10.387 に答える