# 削除規則 モジュールの複数エンティティ間の関係を作成する場合、 **レコードを削除** する際にどのような参照整合性を使用するのかを定義する必要があります。 **参照整合性** によって、エンティティAのレコードが削除されたときにそのエンティティAのレコードを参照しているエンティティBのレコードがどうなるかを指定します。 以下のエンティティ図はCustomer(主エンティティA)とOrder(関連エンティティB)の関係を定義しています。CustomerにはOrderが複数ある場合があり、Orderは1つのCustomerにのみ属します。[参照アトリビュート](https://success.outsystems.com/ja-jp/documentation/11/building_apps/data_management/data_modeling/entity_relationships/)(データベース用語の外部キーに相当)は、エンティティ **Order** のアトリビュート **CustomerId** です。 ![エンティティAであるCustomerと参照アトリビュートCustomerIdを持つエンティティBであるOrderの関係を示す図](https://success.outsystems.com/TK_Resource/6d54fe65-7cc4-41de-bbe5-686e24f759ba "Entity Relationship Diagram for Customers and Orders") この例の場合、 **参照整合性** を指定することで、Customerが削除されたときにCustomerのOrderがどうなるかを定義します。 2つのエンティティ間の関係で **参照整合性** を指定するには、関連エンティティの **参照アトリビュート** を編集し、 **Delete Rule** プロパティの値を`Protect`、`Delete`、`Ignore`のいずれかに設定する必要があります。 ![Delete RuleプロパティのドロップダウンメニューのProtect、Delete、Ignoreの各オプションのスクリーンショット](https://success.outsystems.com/TK_Resource/dc5a3ab4-86a3-4f5a-a8aa-9250db2d3a0b "Referential Integrity Delete Rule Options") **Protect** **Delete Rule** を`Protect`に設定すると、関連エンティティ内に関連するレコードがある場合は、主エンティティのレコードは削除されません。 この動作は参照アトリビュートで作成されたデータベース制約によって確保されます。 関連エンティティに関連するレコードをまだ持っている主エンティティのレコードを削除しようとすると、Platform Serverがデータベース例外を返し、操作は実行されません。 **Delete(削除)** **Delete Rule** を`Delete`に設定した場合、主エンティティのレコードを削除すると、関連エンティティ内の関連するレコードもすべて削除されます。この仕組みは一般的に「カスケード削除」として知られています。 この動作は参照アトリビュートで作成されたデータベース制約によって確保されます。 **Ignore** **Delete Rule** を`Ignore`に設定した場合、関連エンティティ内の関連するレコードを保持したまま、主エンティティのレコードを削除できます。 `Ignore`値では参照整合性は保証されないため、データベース制約は発生しません。そのため、 **Delete Rule** プロパティの値を前のものから`Ignore`に変更した場合、対応する自動インデックスは削除されます(いずれかのプロパティを手動で変更した場合を除きます)。 エクステンションにより公開されている外部エンティティを外部キーアトリビュートが参照している場合、参照整合性を保証することができないため、使用可能な **Delete Rule** プロパティの値は`Ignore`のみです。 エンティティモデルを設計するとき、複数の関係のDelete Ruleを適切に設定し、システムが各ユースケースで期待どおりに動作するようにする必要があります。 ユースケースに応じて適切な選択を行うために役立つ、各オプションの例と考慮事項を以下に示します。 ## 「Protect」の例 `Protect`値がよく使用されるのは、エンドユーザーがアプリケーションの画面から直接エンティティデータを削除できる場合です。 次のようなビジネスシナリオについて考えます。 - There is an application screen where the end users can delete **Customers** . - **Customer** には **Order** が複数ある場合があり、 **Order** は1つの **Customer** にのみ属します。 - 関連するOrderがある場合、 **Customer** を削除することはできません。 参照アトリビュート **CustomerId** の **Delete Rule** プロパティを`Protect`に設定すると、エンドユーザーは関連するOrderが残っているCustomerを削除できません。 ![OrderエンティティのCustomerId参照アトリビュートのDelete RuleをProtectに設定する例](https://success.outsystems.com/TK_Resource/cc15d28c-72f7-491d-a3f5-1c4ea3e3c4c8 "Protect Delete Rule Example") 関連するOrderが残っているCustomerを削除しようとするとデータベース例外になり、操作は実行されません。 ![Protect削除規則を使用しているときに関連するOrderがあるCustomerを削除しようとした場合に表示されるエラーメッセージ](https://success.outsystems.com/TK_Resource/fcd6ca3e-3a25-4803-8639-caf34d3ada77 "Database Exception for Protect Delete Rule") この場合、Customerを削除するには、そのCustomerによって行われたOrderを先にすべて削除する必要があります。 この方法はdelete文を個別に制御および最適化することができ、データの整合性も確保されるため、パフォーマンスに優れています。 より高い制御とパフォーマンスを得ようとすると実装コストが高くなるため、どちらかを優先する必要があります。 ### 利点 - 関連エンティティによって参照されている主エンティティのレコードは削除できないため、常にデータモデルの整合性が保たれます。 ### 制約 - ロジック内で削除の順序が適切になるように調整する必要があります。関連エンティティのレコードを先に削除してから主エンティティのレコードを削除する必要があります。 - モデルに新しい関連エンティティを追加するたびに、その関連エンティティを削除サイクルロジックにも含める必要があります。 ## 「Delete」の例 `Delete`値がよく使用されるのは、データパージメカニズムを実装するときに、モデル全体の間で自動カスケード削除を行う必要がある場合です。 通常、データパージメカニズムは非同期プロセス(タイマーまたはBPT)により処理されるため、パフォーマンスには影響しません。 次のようなビジネスシナリオについて考えます。 - 5年以上前の終了済みの **Order** をすべて削除します。 - **Order** には **OrderItem** が1つまたは複数あり、 **OrderItem** は1つの **Order** にのみ属します。 - **Order** が削除されたときに、関連する **OrderItem** もすべて削除される必要があります。 参照アトリビュート **OrderId** の **Delete Rule** プロパティを`Delete`に設定すると、Orderが削除されたときに、関連するOrderItemもすべて自動的に削除されます。 ![Delete RuleをDeleteに設定することでOrderを削除すると関連するOrderItemも削除されるカスケード削除の例](https://success.outsystems.com/TK_Resource/3e889dda-16be-41af-afd2-c6359e2186c8 "Cascade Delete with Delete Rule Example") ### 利点 - 常にデータモデルの整合性が保たれます。 主エンティティのレコードを削除すると、関連エンティティの関連するレコードもすべて削除されるため、関連エンティティでレコードが参照されなくなります。 - 主エンティティレベルでのみレコードを削除すればよいため、削除ロジックの開発と保守が簡単です。 - 参照アトリビュートの **Delete Rule** を`Delete`に設定するだけでよいため、新しい関連エンティティをモデルに追加するときの開発労力が少なくてすみます。 ### 制約 - この方法では、関連レコードの数によってパフォーマンスが低下する可能性があります。 削除操作のたびに関連エンティティの関連レコードを確認するため、delete文の実行に時間がかかります。 このため、エンティティモデルが複雑でパフォーマンスが重要である場合(エンドユーザーがアプリケーションの画面から直接エンティティデータを削除できる場合など)、この方法は推奨されません。 ## 「Ignore」の例 Ignore値がよく使用されるのは、履歴データアーカイブメカニズムを実装するときに、主エンティティのレコードは削除するが、主レコードの詳細が関連しないことを考慮して、関連エンティティのレコードをすべて保持する必要がある場合です。 次のようなビジネスシナリオについて考えます。 - **Order** に対して実行されたすべての操作のログが **OrderHistory** に記録されます。 - 1つの **OrderHistory** レコードは1つの **Order** にのみ関連し、1つの **Order** には関連する **OrderHistory** レコードが1つまたは複数あります。 - 5年以上前の終了済みの **Order** をすべて削除します。ただし、コンプライアンス上の理由により、 **OrderHistory** レコードを10年間保持する必要があります。 参照アトリビュート **OrderId** の **Delete Rule** プロパティを`Ignore`に設定することにより、Orderを削除し、関連するOrderHistoryレコードは保持することができます。 ![Ignore削除規則を使用して関連するOrderHistoryレコードを保持したままOrderを削除する例](https://success.outsystems.com/TK_Resource/4db004db-26cd-4f3f-a784-75e1efc97644 "Ignore Delete Rule for Historical Data Archiving") ### 利点 - 関連エンティティに影響を及ぼすことなく、主エンティティのレコードを削除することができます。 ### 制約 - この方法を使用するとデータモデルが不整合になります。 関連レコードは保持されますが、主レコードの詳細を取得することはできず、取得できるのは識別子のみになります。 - 参照アトリビュートの **Delete Rule** プロパティの値を前のものから`Ignore`に変更した場合、対応する自動インデックスは削除されます。参照アトリビュートをクエリフィルタとして使用する場合、新しいインデックスを手動で追加する必要があります。