2016-07-25 15 views
2

私はいつも外来キー制約を使用するように教えられてきたので、これは奇妙な質問です。しかし、私は、参照が削除されたときに、歴史的な目的のために外部キー参照値を保持しなければならない場合があります。外部キーには常に制約が必要ですか?

これは、タスクオカレンスが繰り返しルールを含む親タスクを参照するタスク管理システムです。この親タスクは削除できますが、オカレンス自体は存在しない親IDと一致する必要があります。親タスクが見つからない場合、システムは単純にエラーを返します。たとえば、「親タスクはもう存在しません」。カスケードで親IDをnullに設定できない理由は、そのIDが識別キーとしてオカレンス内の他の場所で使用されているためです。

もう1つの例:プレイリストから削除されたYouTube動画はどうですか?同様の状況の権利ですか?プレイリストで参照されていますが、ビデオが存在しないため、代わりにプレイリストにエラーが返されます。

私は単純に外部キーを定義せず、parent_id参照列を通常の列として作成するだけですか?私はちょうど1つのテーブルが別のテーブルを参照するケースに遭遇したときに、これが通常どのように処理されるかを確かめたいが、前者は後者の存在によって制約を受けない。

+0

技術的には、 'ON DELETE SET NULL'という原因がこれを処理します。あなたの質問が理論的であれば:はい、することができます:) – Koshinae

答えて

4

制約を持つことは、データベースに対して定義されたセマンティクスを実施するための単なるヘルパーに過ぎません。つまり、「この列にはINTEGER(32)だけでなく、他のテーブルのレコードの識別子も含まれています。そのため、彼らは厳密には必要ではないですが、それ:

  • が与え
  • を挿入される不正なデータを防止することにより、「クリーン」なあなたのデータを保持します
  • (自己のドキュメント)フィールドの意図が明確になりますデータベースエンジンは、データベースのより効率的な実行を可能にするテーブルの内容に関するヒントを提供する。

つまり、あなたが説明したことを達成するための「適切な」方法は、まず最初に親レコードを物理的に削除しないことです。代わりに、親を削除済みとしてマークします。歴史的な目的のために記録を残しているので、たとえそれがもはや有効でなくても、親が何をしていたのかを知ることができるようになりたいでしょう。

第2のオプションは、ダミーの "親レコード削除"参照を作成することです。親を削除するときは、残りの参照をダミーレコードを指すように更新します。少なくとも期待どおりの有効な動作を実装するためにエラーに頼ることはありません。

最後に、外部キーをNULLに設定できないようにすべき理由はありません。問題のレコードの主キーの一部として外部キーを使用しているようです(「識別キーとして使用されています」)。これは問題の根本的な原因であれば、やってはいけないことです。それを変更することから始めます。

+0

私はソフト削除について考えましたが、親タスクは別のユーザーが作成することができます。他のユーザーはこの親タスクにサブスクライブすることができます。そのため、タスクが発生します。ただし、元のタスクを作成した元のユーザーがそのタスクを削除したい場合、予期される結果はデー​​タベースから削除され、その出現は購読している他のユーザーのレコードとして保持されます。私はレコードの所有者が明示的にそれを要求したときにレコードを削除しないことはOK(または法律上)ですか? – chaser

+0

元のタスクが5つのサブタスクにグループ分けされているため、外部キーをNULLに設定できません。これらのグループ化は、すべての発生状況に影響を与える必要があるため、キーを特定する必要があります。 – chaser

+0

グループ化の問題のため、2番目のオプションについてはわかりません - 基本的にNULLオプションに似ています。しかし、私はIDのを除いて、他のすべてをNULLに設定したと仮定します...それは働くことができますか?少なくともそれは実際の内容のないソフト削除のようなものです - それは削除の所有者の期待に応えます... NULLでいっぱいのテーブルは間違っています...私はこれについてもう少し考える必要があります。 .. – chaser

0

外部キーを定義するだけではなく、単に parent_id参照列を通常の列として作成するだけですか?

はい。少なくともこれは私が知るべき方法であり、私たちは仕事でこれをどう扱うのかです。

次に、参照列にインデックスを設定したい場合があります。