SQL Serverで外部キーを設定する場合、どのような状況で削除または更新時にカスケードする必要がありますか?その背後にある理由は何ですか?
これはおそらく他のデータベースにも当てはまります。
私は、各シナリオの具体的な例として、できればそれらをうまく使用した人からの検索をしています。
SQL Serverで外部キーを設定する場合、どのような状況で削除または更新時にカスケードする必要がありますか?その背後にある理由は何ですか?
これはおそらく他のデータベースにも当てはまります。
私は、各シナリオの具体的な例として、できればそれらをうまく使用した人からの検索をしています。
回答:
これまでに見てきたことの要約:
外部キーは、データベースの参照整合性を保証するための最良の方法です。魔法のせいでカスケードを回避することは、コンパイラの背後にある魔法を信頼しないので、アセンブリですべてを書くようなものです。
悪い点は、例えば、逆にそれらを作成するような外部キーの間違った使い方です。
Juan Manuelの例は標準的な例です。コードを使用すると、データベースに偽のDocumentItemが残り、あなたに噛まれる可能性が高くなります。
カスケード更新は、たとえば、ユーザーテーブルの主キーが名前と姓の組み合わせであるなど、変更可能なものによってデータへの参照がある場合に役立ちます。次に、その組み合わせの変更を参照先に反映させます。
@Aidanは、あなたはを参照することを明快には、高コストであるデータベースに偽のデータを残すチャンス来る小さくはないが。私にとって、それは通常、DBに精通していないことと、DBを操作する前にどのFKが配置されているかを見つけることができないことがその恐れを助長していることです。それ、またはカスケードの継続的な誤用、エンティティが概念的に関連していない場所、または履歴を保持する必要がある場所でのカスケードの使用。
カスケード削除は使用しません。
データベースから何かを削除したい場合は、取り出したいものをデータベースに明示的に伝えたいです。
もちろん、それらはデータベースで使用可能な関数であり、それらを使用しても問題ない場合があります。たとえば、「order」テーブルと「orderItem」テーブルがある場合、削除するときにアイテムをクリアすることができます。注文。
「マジック」が発生するのではなく、コード(またはストアドプロシージャ)でそれを行うことで得られる明快さが好きです。
同じ理由で、私もトリガーのファンではありません。
注目すべき点は、「order」を削除すると、カスケード削除によって50個の「orderItem」が削除された場合でも、「1行の影響」レポートが返されることです。
私はカスケード削除でよく働きます。
データベースに反対する誰もが不要なデータを残さない可能性があることを知っておくのは良いことです。依存関係が大きくなった場合は、Management Studioのダイアグラムで制約を変更するだけで、spやdataaccesを微調整する必要はありません。
とはいえ、削除のカスケードと循環参照に関する問題が1つあります。これにより、データベースの一部に連鎖的な削除がないことがよくあります。
私は多くのデータベース作業を行っており、カスケード削除が役立つとは限りません。私がそれらを効果的に使用したのは、夜間のジョブによって更新されるレポートデータベースの場合です。前回のインポート以降に変更された最上位のレコードを削除して、変更されたデータが正しくインポートされることを確認します。次に、変更されたレコードとそれらに関連するものを再インポートします。データベースの下部から上部に向かって複雑な削除をたくさん書く必要がなくなります。
カスケード削除はデータを削除するだけなので、トリガーと同じくらい悪いとは考えていません。トリガーはあらゆる種類の厄介なものを内部に持つことができます。
一般に、私は実際の削除を完全に回避し、代わりに論理削除(つまり、trueに設定されるisDeletedと呼ばれるビット列を持つ)を使用します。
あなたがしたい場合は、子テーブルの行を削除する場合は、対応する行が削除された親テーブルで。
カスケード削除を使用しない場合、参照整合性のためにエラーが発生します。
主キーの変更を更新したい場合外部キー
DBAや "会社のポリシー"で、 "On Delete Cascade"(およびその他)の使用を純粋に禁止していると聞いたことがあります。あるケースでは、ある男が3つのトリガーを作成し、その結果、お互いを呼び出しました。3日間の回復により、トリガーの全面的な禁止が行われました。これは、すべて1つのイジットのアクションによるものです。
もちろん、一部の子データを保持する必要がある場合など、「削除時のカスケード」の代わりにトリガーが必要になる場合があります。しかし、他の場合では、On Deleteカスケードメソッドを使用することが完全に有効です。「削除時カスケード」の主な利点は、すべての子をキャプチャすることです。カスタムで記述されたトリガー/ストアプロシージャは、正しくコーディングされていない場合、失敗する可能性があります。
開発者には、開発内容と仕様に基づいて決定を下すことを認めるべきだと思います。悪い経験に基づくカーペットの禁止は、基準とすべきではありません。「使用しない」思考プロセスは、せいぜい厳格です。毎回、判断を下す必要があり、ビジネスモデルの変化に応じて変更を加える必要があります。
これが開発のすべてではありませんか?
(コードで行うのではなく)カスケード削除を行う1つの理由は、パフォーマンスを向上させることです。
ケース1:カスケード削除を使用する
DELETE FROM table WHERE SomeDate < 7 years ago;
ケース2:カスケード削除なし
FOR EACH R IN (SELECT FROM table WHERE SomeDate < 7 years ago) LOOP
DELETE FROM ChildTable WHERE tableId = R.tableId;
DELETE FROM table WHERE tableId = R.tableid;
/* More child tables here */
NEXT
次に、カスケード削除を使用して子テーブルを追加すると、ケース1のコードが機能し続けます。
私は、関係のセマンティクスが「一部」であるカスケードにのみ入れます。そうしないと、一部の馬鹿はあなたが行うときにデータベースの半分を削除します:
DELETE FROM CURRENCY WHERE CurrencyCode = 'USD'
SQLサーバーで明示的に要求しなかった削除または更新を回避しようとしています。
カスケードまたはトリガーを使用する。彼らは、バグを追跡しようとするとき、またはパフォーマンスの問題を診断するときのいずれかの時点で、いつかお尻を噛む傾向があります。
それらをどこで使用するかは、あまり努力を払わずに一貫性を保証することです。同じ効果を得るには、ストアドプロシージャを使用する必要があります。
異なるバージョンの多数の異なるモジュールを含むシステムで作業している場合、カスケード削除されたアイテムがPKホルダーの一部であるか、PKホルダーによって所有されていると、非常に役立ちます。そうしないと、すべてのモジュールでPK所有者を削除する前に依存アイテムをクリーンアップするための即時パッチが必要になるか、外部キー関係が完全に省略され、クリーンアップが正しく実行されない場合、システムに大量のゴミが残る可能性があります。
カスケード削除がかなり前から推奨されていなかった後、2つの既存のテーブル間の新しい交差テーブル(削除する交差のみ)にカスケード削除を導入しました。データが失われたとしても、それほど悪くはありません。
ただし、列挙型のようなリストテーブルでは悪いことです。誰かがエントリ13-テーブル「色」から黄色を削除し、データベース内のすべての黄色のアイテムが削除されます。また、これらは時々delete-all-insert-allの方法で更新されるため、参照整合性が完全に省略されます。もちろんそれは間違っていますが、真の参照整合性の導入が予期しない副作用のリスクがある状態で、長年実行されている複雑なソフトウェアをどのように変更しますか?
別の問題は、主キーが削除された後でも元の外部キー値が保持される場合です。元のFKにトゥームストーン列とON DELETE SET NULLオプションを作成できますが、これにもトリガー(またはPK削除後を除く)のキー値を維持するための特定のコードが必要です。
カスケード削除は、物理データベースに論理スーパータイプおよびサブタイプのエンティティを実装する場合に非常に役立ちます。
個別のスーパータイプテーブルとサブタイプテーブルを使用してスーパータイプ/サブタイプを物理的に実装する場合(すべてのサブタイプ属性を単一の物理スーパータイプテーブルにロールアップするのではなく)、1対1 -これらのテーブルと問題の1つの関係は、これらのテーブル間で主キーを100%同期させる方法になります。
カスケード削除は、次の場合に非常に役立つツールです。
1)スーパータイプのレコードを削除すると、対応する単一のサブタイプのレコードも削除されることを確認してください。
2)サブタイプのレコードを削除すると、スーパータイプのレコードも削除されることを確認してください。これは、サブタイプテーブルに "instead-of"削除トリガーを実装して、対応するスーパータイプレコードを削除することで実現されます。これにより、サブタイプレコードがカスケード削除されます。
この方法でカスケード削除を使用すると、スーパータイプレコードを最初に削除するか、サブタイプレコードを最初に削除するかに関係なく、孤立したスーパータイプまたはサブタイプレコードが存在しないことが保証されます。
sql-server
タグを削除すると、コミュニティにとってより便利になります。